taster 3.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- taster-3.1.0/.claude/settings.local.json +48 -0
- taster-3.1.0/.github/workflows/claude-code-review.yml +57 -0
- taster-3.1.0/.github/workflows/claude.yml +50 -0
- taster-3.1.0/.github/workflows/publish.yml +32 -0
- taster-3.1.0/.gitignore +53 -0
- taster-3.1.0/CHANGELOG.md +38 -0
- taster-3.1.0/PKG-INFO +549 -0
- taster-3.1.0/README.md +474 -0
- taster-3.1.0/VIDEO_CLASSIFICATION_GUIDE.md +278 -0
- taster-3.1.0/assets/Readme_Logo.png +0 -0
- taster-3.1.0/assets/Social_Preview_Logo.png +0 -0
- taster-3.1.0/classify_folder.bat +43 -0
- taster-3.1.0/clear_failed_for_retry.py +342 -0
- taster-3.1.0/config.yaml +291 -0
- taster-3.1.0/examples/README.md +34 -0
- taster-3.1.0/examples/sample_taste_preferences.json +64 -0
- taster-3.1.0/generate_taste_profile.py +555 -0
- taster-3.1.0/learn_from_reviews.py +277 -0
- taster-3.1.0/mcp_server.py +44 -0
- taster-3.1.0/profiles/code-review.json +66 -0
- taster-3.1.0/profiles/default-documents.json +65 -0
- taster-3.1.0/profiles/default-photos.json +71 -0
- taster-3.1.0/profiles/product-photos.json +71 -0
- taster-3.1.0/profiles/student-essays.json +69 -0
- taster-3.1.0/profiles/vacation-social-media.json +82 -0
- taster-3.1.0/pyproject.toml +84 -0
- taster-3.1.0/reprocess_failed.py +565 -0
- taster-3.1.0/serve.py +20 -0
- taster-3.1.0/sommelier/__init__.py +2 -0
- taster-3.1.0/sommelier/api/__init__.py +4 -0
- taster-3.1.0/sommelier/api/app.py +44 -0
- taster-3.1.0/sommelier/api/models.py +194 -0
- taster-3.1.0/sommelier/api/routers/__init__.py +1 -0
- taster-3.1.0/sommelier/api/routers/classify.py +55 -0
- taster-3.1.0/sommelier/api/routers/profiles.py +51 -0
- taster-3.1.0/sommelier/api/routers/results.py +66 -0
- taster-3.1.0/sommelier/api/routers/training.py +43 -0
- taster-3.1.0/sommelier/api/services/__init__.py +0 -0
- taster-3.1.0/sommelier/api/services/classification_service.py +263 -0
- taster-3.1.0/sommelier/api/services/profile_service.py +161 -0
- taster-3.1.0/sommelier/api/services/training_service.py +217 -0
- taster-3.1.0/sommelier/classification/__init__.py +10 -0
- taster-3.1.0/sommelier/classification/classifier.py +708 -0
- taster-3.1.0/sommelier/classification/prompt_builder.py +504 -0
- taster-3.1.0/sommelier/classification/routing.py +337 -0
- taster-3.1.0/sommelier/cli.py +485 -0
- taster-3.1.0/sommelier/compat.py +23 -0
- taster-3.1.0/sommelier/core/__init__.py +48 -0
- taster-3.1.0/sommelier/core/ai_client.py +97 -0
- taster-3.1.0/sommelier/core/cache.py +444 -0
- taster-3.1.0/sommelier/core/config.py +347 -0
- taster-3.1.0/sommelier/core/file_utils.py +374 -0
- taster-3.1.0/sommelier/core/logging_config.py +173 -0
- taster-3.1.0/sommelier/core/media_prep.py +149 -0
- taster-3.1.0/sommelier/core/models.py +537 -0
- taster-3.1.0/sommelier/core/profiles.py +422 -0
- taster-3.1.0/sommelier/core/provider_factory.py +109 -0
- taster-3.1.0/sommelier/core/providers/__init__.py +6 -0
- taster-3.1.0/sommelier/core/providers/anthropic_provider.py +213 -0
- taster-3.1.0/sommelier/core/providers/gemini.py +5 -0
- taster-3.1.0/sommelier/core/providers/openai_provider.py +204 -0
- taster-3.1.0/sommelier/dirs.py +79 -0
- taster-3.1.0/sommelier/features/__init__.py +15 -0
- taster-3.1.0/sommelier/features/burst_detector.py +333 -0
- taster-3.1.0/sommelier/features/document_features.py +410 -0
- taster-3.1.0/sommelier/features/embeddings.py +322 -0
- taster-3.1.0/sommelier/features/quality.py +404 -0
- taster-3.1.0/sommelier/mcp/__init__.py +4 -0
- taster-3.1.0/sommelier/mcp/server.py +1403 -0
- taster-3.1.0/sommelier/pipelines/__init__.py +13 -0
- taster-3.1.0/sommelier/pipelines/base.py +224 -0
- taster-3.1.0/sommelier/pipelines/document_pipeline.py +134 -0
- taster-3.1.0/sommelier/pipelines/mixed_pipeline.py +88 -0
- taster-3.1.0/sommelier/pipelines/photo_pipeline.py +210 -0
- taster-3.1.0/sommelier/training/__init__.py +13 -0
- taster-3.1.0/sommelier/training/sampler.py +220 -0
- taster-3.1.0/sommelier/training/session.py +265 -0
- taster-3.1.0/sommelier/training/synthesizer.py +555 -0
- taster-3.1.0/taste_classify.py +316 -0
- taster-3.1.0/taste_preferences.json +54 -0
- taster-3.1.0/taste_preferences_generated.json +64 -0
- taster-3.1.0/taste_trainer.py +591 -0
- taster-3.1.0/tests/__init__.py +1 -0
- taster-3.1.0/tests/test_api.py +443 -0
- taster-3.1.0/tests/test_cache.py +231 -0
- taster-3.1.0/tests/test_classification.py +285 -0
- taster-3.1.0/tests/test_classifier_extended.py +540 -0
- taster-3.1.0/tests/test_cli.py +154 -0
- taster-3.1.0/tests/test_compat.py +65 -0
- taster-3.1.0/tests/test_config.py +188 -0
- taster-3.1.0/tests/test_config_resolution.py +129 -0
- taster-3.1.0/tests/test_dirs.py +165 -0
- taster-3.1.0/tests/test_end_to_end.py +343 -0
- taster-3.1.0/tests/test_error_tracking.py +377 -0
- taster-3.1.0/tests/test_features.py +480 -0
- taster-3.1.0/tests/test_file_utils.py +236 -0
- taster-3.1.0/tests/test_integration_smoke.py +123 -0
- taster-3.1.0/tests/test_mcp_handlers.py +457 -0
- taster-3.1.0/tests/test_mcp_training.py +99 -0
- taster-3.1.0/tests/test_models_extended.py +334 -0
- taster-3.1.0/tests/test_pipelines.py +302 -0
- taster-3.1.0/tests/test_profiles_extended.py +294 -0
- taster-3.1.0/tests/test_providers.py +507 -0
- taster-3.1.0/tests/test_routing_extended.py +339 -0
- taster-3.1.0/tests/test_synthesizer.py +272 -0
- taster-3.1.0/tests/test_training_sampler.py +212 -0
- taster-3.1.0/tests/test_training_session.py +233 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"permissions": {
|
|
3
|
+
"allow": [
|
|
4
|
+
"Bash(python:*)",
|
|
5
|
+
"Bash(nul)",
|
|
6
|
+
"Bash(for dir in \"E:\\Dropbox\\Camera Roll\\2025_sorted\"/*)",
|
|
7
|
+
"Bash(done)",
|
|
8
|
+
"Bash(xargs -I {} python -c \"from PIL import Image; print(Image.open(''''{}'''').size)\")",
|
|
9
|
+
"WebFetch(domain:ai.google.dev)",
|
|
10
|
+
"Bash(mkdir:*)",
|
|
11
|
+
"Bash(git mv test_*.py analyze_missing_files.py check_babygate_cache.py check_gemini_cache_babygate.py find_failed_embeddings.py find_missing_files.py find_missing_videos.py trace_missing_files.py missing_files_list.txt old/tests/)",
|
|
12
|
+
"Bash(mv:*)",
|
|
13
|
+
"Bash(git add:*)",
|
|
14
|
+
"Bash(git commit:*)",
|
|
15
|
+
"Bash(dir /s \"E:\\OneDrive\\Evie and Elle\\LLM Taste Cloner\" /b)",
|
|
16
|
+
"Bash(dir:*)",
|
|
17
|
+
"Bash(tree:*)",
|
|
18
|
+
"Bash(tar:*)",
|
|
19
|
+
"Bash(powershell -Command:*)",
|
|
20
|
+
"Bash(powershell -ExecutionPolicy Bypass -File \"E:\\OneDrive\\Evie and Elle\\Sommelier\\create_zip.ps1\")",
|
|
21
|
+
"WebSearch",
|
|
22
|
+
"Bash(cat:*)",
|
|
23
|
+
"Bash(git push:*)",
|
|
24
|
+
"Bash(gh pr create --title \"Add error tracking and automatic retry for classification failures\" --body \"$\\(cat <<''EOF''\n## Summary\n\n- **Error Tracking**: Failed classifications now include structured error metadata \\(`is_error_fallback`, `error_type`, `error_message`, `retry_count`\\) enabling easy identification and reprocessing\n- **Automatic Retry**: API failures \\(timeouts, rate limits, connection errors\\) trigger up to 2 automatic retries with exponential backoff \\(2s, 4s\\)\n- **Burst-Aware Reprocessing**: New `clear_failed_for_retry.py` script clears entire bursts when any photo in the burst failed, preserving grouping context\n- **Context-Aware Prompts**: When retrying burst photos as singletons, includes context about sibling classifications\n\n## Changes\n\n### Core Classification\n- `src/classification/classifier.py`: Added `_create_fallback_response\\(\\)` with error fields, `_execute_with_retry\\(\\)` wrapper, burst context storage\n- `src/classification/prompt_builder.py`: Added `build_singleton_with_burst_context\\(\\)` for context-aware retry\n\n### Configuration\n- `src/core/config.py`: Added `classification_retries`, `retry_delay_seconds`, `retry_on_errors` settings\n- `config.yaml`: Added retry configuration section\n- `src/core/cache.py`: Added `burst_context` cache type\n\n### Reporting\n- `taste_classify.py`: Updated CSV reports to include error tracking columns\n\n### New Scripts\n- `clear_failed_for_retry.py`: Identifies photos with error fallbacks, clears cache and sorted folders for re-classification\n- `reprocess_failed.py`: Standalone reprocessing with burst context awareness\n\n### Documentation & Tests\n- `README.md`: Added Error Tracking & Retry section, updated version to 2.2.0\n- `tests/test_error_tracking.py`: 20+ unit tests for error tracking and retry functionality\n\n## Test plan\n\n- [x] Unit tests pass \\(`pytest tests/test_error_tracking.py -v`\\)\n- [ ] Run `clear_failed_for_retry.py` with `--dry-run` on a sorted folder with known failures\n- [ ] Clear failed photos and verify re-classification works correctly\n- [ ] Verify CSV reports include new error tracking columns\n\n🤖 Generated with [Claude Code]\\(https://claude.com/claude-code\\)\nEOF\n\\)\")",
|
|
25
|
+
"Bash(gh pr view:*)",
|
|
26
|
+
"Bash(gh pr diff:*)",
|
|
27
|
+
"Bash(gh pr merge:*)",
|
|
28
|
+
"Bash(pip install:*)",
|
|
29
|
+
"Bash(curl:*)",
|
|
30
|
+
"Bash(taskkill:*)",
|
|
31
|
+
"Bash(pkill:*)",
|
|
32
|
+
"Bash(tasklist:*)",
|
|
33
|
+
"Bash(gh repo view:*)",
|
|
34
|
+
"Bash(gh repo rename:*)",
|
|
35
|
+
"Bash(gh repo edit:*)",
|
|
36
|
+
"Bash(pip show:*)",
|
|
37
|
+
"Bash(printf:*)",
|
|
38
|
+
"Bash(echo:*)",
|
|
39
|
+
"Bash(git log:*)",
|
|
40
|
+
"Bash(find:*)",
|
|
41
|
+
"Bash(ls:*)",
|
|
42
|
+
"Bash(cd:*)",
|
|
43
|
+
"Bash(grep:*)"
|
|
44
|
+
],
|
|
45
|
+
"deny": [],
|
|
46
|
+
"ask": []
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
name: Claude Code Review
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
types: [opened, synchronize]
|
|
6
|
+
# Optional: Only run on specific file changes
|
|
7
|
+
# paths:
|
|
8
|
+
# - "src/**/*.ts"
|
|
9
|
+
# - "src/**/*.tsx"
|
|
10
|
+
# - "src/**/*.js"
|
|
11
|
+
# - "src/**/*.jsx"
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
claude-review:
|
|
15
|
+
# Optional: Filter by PR author
|
|
16
|
+
# if: |
|
|
17
|
+
# github.event.pull_request.user.login == 'external-contributor' ||
|
|
18
|
+
# github.event.pull_request.user.login == 'new-developer' ||
|
|
19
|
+
# github.event.pull_request.author_association == 'FIRST_TIME_CONTRIBUTOR'
|
|
20
|
+
|
|
21
|
+
runs-on: ubuntu-latest
|
|
22
|
+
permissions:
|
|
23
|
+
contents: read
|
|
24
|
+
pull-requests: read
|
|
25
|
+
issues: read
|
|
26
|
+
id-token: write
|
|
27
|
+
|
|
28
|
+
steps:
|
|
29
|
+
- name: Checkout repository
|
|
30
|
+
uses: actions/checkout@v4
|
|
31
|
+
with:
|
|
32
|
+
fetch-depth: 1
|
|
33
|
+
|
|
34
|
+
- name: Run Claude Code Review
|
|
35
|
+
id: claude-review
|
|
36
|
+
uses: anthropics/claude-code-action@v1
|
|
37
|
+
with:
|
|
38
|
+
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
|
|
39
|
+
prompt: |
|
|
40
|
+
REPO: ${{ github.repository }}
|
|
41
|
+
PR NUMBER: ${{ github.event.pull_request.number }}
|
|
42
|
+
|
|
43
|
+
Please review this pull request and provide feedback on:
|
|
44
|
+
- Code quality and best practices
|
|
45
|
+
- Potential bugs or issues
|
|
46
|
+
- Performance considerations
|
|
47
|
+
- Security concerns
|
|
48
|
+
- Test coverage
|
|
49
|
+
|
|
50
|
+
Use the repository's CLAUDE.md for guidance on style and conventions. Be constructive and helpful in your feedback.
|
|
51
|
+
|
|
52
|
+
Use `gh pr comment` with your Bash tool to leave your review as a comment on the PR.
|
|
53
|
+
|
|
54
|
+
# See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
|
|
55
|
+
# or https://docs.claude.com/en/docs/claude-code/cli-reference for available options
|
|
56
|
+
claude_args: '--allowed-tools "Bash(gh issue view:*),Bash(gh search:*),Bash(gh issue list:*),Bash(gh pr comment:*),Bash(gh pr diff:*),Bash(gh pr view:*),Bash(gh pr list:*)"'
|
|
57
|
+
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
name: Claude Code
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
issue_comment:
|
|
5
|
+
types: [created]
|
|
6
|
+
pull_request_review_comment:
|
|
7
|
+
types: [created]
|
|
8
|
+
issues:
|
|
9
|
+
types: [opened, assigned]
|
|
10
|
+
pull_request_review:
|
|
11
|
+
types: [submitted]
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
claude:
|
|
15
|
+
if: |
|
|
16
|
+
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
|
|
17
|
+
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
|
|
18
|
+
(github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) ||
|
|
19
|
+
(github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')))
|
|
20
|
+
runs-on: ubuntu-latest
|
|
21
|
+
permissions:
|
|
22
|
+
contents: read
|
|
23
|
+
pull-requests: read
|
|
24
|
+
issues: read
|
|
25
|
+
id-token: write
|
|
26
|
+
actions: read # Required for Claude to read CI results on PRs
|
|
27
|
+
steps:
|
|
28
|
+
- name: Checkout repository
|
|
29
|
+
uses: actions/checkout@v4
|
|
30
|
+
with:
|
|
31
|
+
fetch-depth: 1
|
|
32
|
+
|
|
33
|
+
- name: Run Claude Code
|
|
34
|
+
id: claude
|
|
35
|
+
uses: anthropics/claude-code-action@v1
|
|
36
|
+
with:
|
|
37
|
+
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
|
|
38
|
+
|
|
39
|
+
# This is an optional setting that allows Claude to read CI results on PRs
|
|
40
|
+
additional_permissions: |
|
|
41
|
+
actions: read
|
|
42
|
+
|
|
43
|
+
# Optional: Give a custom prompt to Claude. If this is not specified, Claude will perform the instructions specified in the comment that tagged it.
|
|
44
|
+
# prompt: 'Update the pull request description to include a summary of changes.'
|
|
45
|
+
|
|
46
|
+
# Optional: Add claude_args to customize behavior and configuration
|
|
47
|
+
# See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
|
|
48
|
+
# or https://docs.claude.com/en/docs/claude-code/cli-reference for available options
|
|
49
|
+
# claude_args: '--allowed-tools Bash(gh pr:*)'
|
|
50
|
+
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags: ["v*"]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
publish:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
permissions:
|
|
11
|
+
id-token: write # Trusted Publishing (OIDC)
|
|
12
|
+
contents: write # GitHub Release creation
|
|
13
|
+
steps:
|
|
14
|
+
- uses: actions/checkout@v4
|
|
15
|
+
|
|
16
|
+
- uses: actions/setup-python@v5
|
|
17
|
+
with:
|
|
18
|
+
python-version: "3.12"
|
|
19
|
+
|
|
20
|
+
- name: Install build tools
|
|
21
|
+
run: pip install build
|
|
22
|
+
|
|
23
|
+
- name: Build sdist and wheel
|
|
24
|
+
run: python -m build
|
|
25
|
+
|
|
26
|
+
- name: Publish to PyPI
|
|
27
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
28
|
+
|
|
29
|
+
- name: Create GitHub Release
|
|
30
|
+
uses: softprops/action-gh-release@v2
|
|
31
|
+
with:
|
|
32
|
+
generate_release_notes: true
|
taster-3.1.0/.gitignore
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.so
|
|
6
|
+
.Python
|
|
7
|
+
env/
|
|
8
|
+
venv/
|
|
9
|
+
ENV/
|
|
10
|
+
build/
|
|
11
|
+
develop-eggs/
|
|
12
|
+
dist/
|
|
13
|
+
downloads/
|
|
14
|
+
eggs/
|
|
15
|
+
.eggs/
|
|
16
|
+
lib/
|
|
17
|
+
lib64/
|
|
18
|
+
parts/
|
|
19
|
+
sdist/
|
|
20
|
+
var/
|
|
21
|
+
wheels/
|
|
22
|
+
*.egg-info/
|
|
23
|
+
.installed.cfg
|
|
24
|
+
*.egg
|
|
25
|
+
|
|
26
|
+
# IDEs
|
|
27
|
+
.vscode/
|
|
28
|
+
.idea/
|
|
29
|
+
*.swp
|
|
30
|
+
*.swo
|
|
31
|
+
*~
|
|
32
|
+
|
|
33
|
+
# OS
|
|
34
|
+
.DS_Store
|
|
35
|
+
Thumbs.db
|
|
36
|
+
desktop.ini
|
|
37
|
+
|
|
38
|
+
# Environment variables
|
|
39
|
+
.env
|
|
40
|
+
.env.local
|
|
41
|
+
|
|
42
|
+
# Project specific
|
|
43
|
+
.taste_cache/
|
|
44
|
+
old/
|
|
45
|
+
archive/
|
|
46
|
+
Share/
|
|
47
|
+
Storage/
|
|
48
|
+
Review/
|
|
49
|
+
training_data/
|
|
50
|
+
*.log
|
|
51
|
+
*.pkl
|
|
52
|
+
*.json.bak
|
|
53
|
+
.coverage
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 3.0.0 (2026-02-17)
|
|
4
|
+
|
|
5
|
+
**Sommelier is now a distributable PyPI package.**
|
|
6
|
+
|
|
7
|
+
### Breaking Changes
|
|
8
|
+
|
|
9
|
+
- **Package renamed:** `src/` is now `sommelier/`. All imports change from `from src.*` to `from sommelier.*`.
|
|
10
|
+
- **`requirements.txt` removed.** Dependencies are now declared in `pyproject.toml` with optional groups.
|
|
11
|
+
- **`setup_sommelier.py` removed.** Replaced by `sommelier init`.
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- **`pip install sommelier`** -- proper Python package with `pyproject.toml` (hatchling build).
|
|
16
|
+
- **CLI entry point** -- `sommelier classify`, `sommelier train`, `sommelier serve`, `sommelier status`, `sommelier init`.
|
|
17
|
+
- **Platform-aware config directory** -- `%APPDATA%\sommelier` (Windows), `~/Library/Application Support/sommelier` (macOS), `$XDG_CONFIG_HOME/sommelier` (Linux).
|
|
18
|
+
- **Config resolution order** -- explicit path > `./config.yaml` > user config dir > built-in defaults. Sommelier works out of the box with zero config.
|
|
19
|
+
- **Optional dependency groups** -- `pip install sommelier[gemini]`, `sommelier[ml]`, `sommelier[all]`, etc. Clear error messages when an optional dep is missing.
|
|
20
|
+
- **`sommelier/compat.py`** -- `require()` helper for graceful optional dependency handling.
|
|
21
|
+
- **`sommelier/dirs.py`** -- platform-aware directory resolution for config, profiles, and .env.
|
|
22
|
+
- **New tests** -- `test_dirs.py`, `test_cli.py`, `test_compat.py`, `test_config_resolution.py`.
|
|
23
|
+
|
|
24
|
+
### Changed
|
|
25
|
+
|
|
26
|
+
- `load_config()` returns defaults when no config file is found (previously raised `FileNotFoundError`).
|
|
27
|
+
- Standalone scripts (`taste_classify.py`, `mcp_server.py`, etc.) still work as thin wrappers for repo-based usage.
|
|
28
|
+
- README updated for cross-platform paths and `pip install` workflow.
|
|
29
|
+
|
|
30
|
+
### Migration
|
|
31
|
+
|
|
32
|
+
If you were using Sommelier from a git clone:
|
|
33
|
+
|
|
34
|
+
1. Pull the latest code.
|
|
35
|
+
2. Run `pip install -e ".[gemini]"` (or whichever provider you use).
|
|
36
|
+
3. Replace `py -3.12 taste_classify.py` with `sommelier classify`.
|
|
37
|
+
4. Replace `py -3.12 setup_sommelier.py` with `sommelier init`.
|
|
38
|
+
5. If you import from Sommelier in your own code, change `from src.*` to `from sommelier.*`.
|