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.
Files changed (107) hide show
  1. taster-3.1.0/.claude/settings.local.json +48 -0
  2. taster-3.1.0/.github/workflows/claude-code-review.yml +57 -0
  3. taster-3.1.0/.github/workflows/claude.yml +50 -0
  4. taster-3.1.0/.github/workflows/publish.yml +32 -0
  5. taster-3.1.0/.gitignore +53 -0
  6. taster-3.1.0/CHANGELOG.md +38 -0
  7. taster-3.1.0/PKG-INFO +549 -0
  8. taster-3.1.0/README.md +474 -0
  9. taster-3.1.0/VIDEO_CLASSIFICATION_GUIDE.md +278 -0
  10. taster-3.1.0/assets/Readme_Logo.png +0 -0
  11. taster-3.1.0/assets/Social_Preview_Logo.png +0 -0
  12. taster-3.1.0/classify_folder.bat +43 -0
  13. taster-3.1.0/clear_failed_for_retry.py +342 -0
  14. taster-3.1.0/config.yaml +291 -0
  15. taster-3.1.0/examples/README.md +34 -0
  16. taster-3.1.0/examples/sample_taste_preferences.json +64 -0
  17. taster-3.1.0/generate_taste_profile.py +555 -0
  18. taster-3.1.0/learn_from_reviews.py +277 -0
  19. taster-3.1.0/mcp_server.py +44 -0
  20. taster-3.1.0/profiles/code-review.json +66 -0
  21. taster-3.1.0/profiles/default-documents.json +65 -0
  22. taster-3.1.0/profiles/default-photos.json +71 -0
  23. taster-3.1.0/profiles/product-photos.json +71 -0
  24. taster-3.1.0/profiles/student-essays.json +69 -0
  25. taster-3.1.0/profiles/vacation-social-media.json +82 -0
  26. taster-3.1.0/pyproject.toml +84 -0
  27. taster-3.1.0/reprocess_failed.py +565 -0
  28. taster-3.1.0/serve.py +20 -0
  29. taster-3.1.0/sommelier/__init__.py +2 -0
  30. taster-3.1.0/sommelier/api/__init__.py +4 -0
  31. taster-3.1.0/sommelier/api/app.py +44 -0
  32. taster-3.1.0/sommelier/api/models.py +194 -0
  33. taster-3.1.0/sommelier/api/routers/__init__.py +1 -0
  34. taster-3.1.0/sommelier/api/routers/classify.py +55 -0
  35. taster-3.1.0/sommelier/api/routers/profiles.py +51 -0
  36. taster-3.1.0/sommelier/api/routers/results.py +66 -0
  37. taster-3.1.0/sommelier/api/routers/training.py +43 -0
  38. taster-3.1.0/sommelier/api/services/__init__.py +0 -0
  39. taster-3.1.0/sommelier/api/services/classification_service.py +263 -0
  40. taster-3.1.0/sommelier/api/services/profile_service.py +161 -0
  41. taster-3.1.0/sommelier/api/services/training_service.py +217 -0
  42. taster-3.1.0/sommelier/classification/__init__.py +10 -0
  43. taster-3.1.0/sommelier/classification/classifier.py +708 -0
  44. taster-3.1.0/sommelier/classification/prompt_builder.py +504 -0
  45. taster-3.1.0/sommelier/classification/routing.py +337 -0
  46. taster-3.1.0/sommelier/cli.py +485 -0
  47. taster-3.1.0/sommelier/compat.py +23 -0
  48. taster-3.1.0/sommelier/core/__init__.py +48 -0
  49. taster-3.1.0/sommelier/core/ai_client.py +97 -0
  50. taster-3.1.0/sommelier/core/cache.py +444 -0
  51. taster-3.1.0/sommelier/core/config.py +347 -0
  52. taster-3.1.0/sommelier/core/file_utils.py +374 -0
  53. taster-3.1.0/sommelier/core/logging_config.py +173 -0
  54. taster-3.1.0/sommelier/core/media_prep.py +149 -0
  55. taster-3.1.0/sommelier/core/models.py +537 -0
  56. taster-3.1.0/sommelier/core/profiles.py +422 -0
  57. taster-3.1.0/sommelier/core/provider_factory.py +109 -0
  58. taster-3.1.0/sommelier/core/providers/__init__.py +6 -0
  59. taster-3.1.0/sommelier/core/providers/anthropic_provider.py +213 -0
  60. taster-3.1.0/sommelier/core/providers/gemini.py +5 -0
  61. taster-3.1.0/sommelier/core/providers/openai_provider.py +204 -0
  62. taster-3.1.0/sommelier/dirs.py +79 -0
  63. taster-3.1.0/sommelier/features/__init__.py +15 -0
  64. taster-3.1.0/sommelier/features/burst_detector.py +333 -0
  65. taster-3.1.0/sommelier/features/document_features.py +410 -0
  66. taster-3.1.0/sommelier/features/embeddings.py +322 -0
  67. taster-3.1.0/sommelier/features/quality.py +404 -0
  68. taster-3.1.0/sommelier/mcp/__init__.py +4 -0
  69. taster-3.1.0/sommelier/mcp/server.py +1403 -0
  70. taster-3.1.0/sommelier/pipelines/__init__.py +13 -0
  71. taster-3.1.0/sommelier/pipelines/base.py +224 -0
  72. taster-3.1.0/sommelier/pipelines/document_pipeline.py +134 -0
  73. taster-3.1.0/sommelier/pipelines/mixed_pipeline.py +88 -0
  74. taster-3.1.0/sommelier/pipelines/photo_pipeline.py +210 -0
  75. taster-3.1.0/sommelier/training/__init__.py +13 -0
  76. taster-3.1.0/sommelier/training/sampler.py +220 -0
  77. taster-3.1.0/sommelier/training/session.py +265 -0
  78. taster-3.1.0/sommelier/training/synthesizer.py +555 -0
  79. taster-3.1.0/taste_classify.py +316 -0
  80. taster-3.1.0/taste_preferences.json +54 -0
  81. taster-3.1.0/taste_preferences_generated.json +64 -0
  82. taster-3.1.0/taste_trainer.py +591 -0
  83. taster-3.1.0/tests/__init__.py +1 -0
  84. taster-3.1.0/tests/test_api.py +443 -0
  85. taster-3.1.0/tests/test_cache.py +231 -0
  86. taster-3.1.0/tests/test_classification.py +285 -0
  87. taster-3.1.0/tests/test_classifier_extended.py +540 -0
  88. taster-3.1.0/tests/test_cli.py +154 -0
  89. taster-3.1.0/tests/test_compat.py +65 -0
  90. taster-3.1.0/tests/test_config.py +188 -0
  91. taster-3.1.0/tests/test_config_resolution.py +129 -0
  92. taster-3.1.0/tests/test_dirs.py +165 -0
  93. taster-3.1.0/tests/test_end_to_end.py +343 -0
  94. taster-3.1.0/tests/test_error_tracking.py +377 -0
  95. taster-3.1.0/tests/test_features.py +480 -0
  96. taster-3.1.0/tests/test_file_utils.py +236 -0
  97. taster-3.1.0/tests/test_integration_smoke.py +123 -0
  98. taster-3.1.0/tests/test_mcp_handlers.py +457 -0
  99. taster-3.1.0/tests/test_mcp_training.py +99 -0
  100. taster-3.1.0/tests/test_models_extended.py +334 -0
  101. taster-3.1.0/tests/test_pipelines.py +302 -0
  102. taster-3.1.0/tests/test_profiles_extended.py +294 -0
  103. taster-3.1.0/tests/test_providers.py +507 -0
  104. taster-3.1.0/tests/test_routing_extended.py +339 -0
  105. taster-3.1.0/tests/test_synthesizer.py +272 -0
  106. taster-3.1.0/tests/test_training_sampler.py +212 -0
  107. 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
@@ -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.*`.