llmcapa 0.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.
@@ -0,0 +1,144 @@
1
+ # Byte-compiled / optimized / DLL support
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ share/python-wheels/
24
+ *.egg-info/
25
+ .installed.cfg
26
+ *.egg
27
+ MANIFEST
28
+
29
+ # PyInstaller
30
+ # Usually these files are written by a python script from a template
31
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
32
+ *.manifest
33
+ *.spec
34
+
35
+ # Installer logs
36
+ pip-log.txt
37
+ pip-delete-this-directory.txt
38
+
39
+ # Unit test / coverage reports
40
+ htmlcov/
41
+ .tox/
42
+ .nox/
43
+ .coverage
44
+ .coverage.*
45
+ .cache
46
+ nosetests.xml
47
+ coverage.xml
48
+ *.cover
49
+ *.py,cover
50
+ .flatpak-builder/
51
+
52
+ # Translations
53
+ *.mo
54
+ *.pot
55
+
56
+ # Django stuff:
57
+ *.log
58
+ local_settings.py
59
+ db.sqlite3
60
+ db.sqlite3-journal
61
+
62
+ # Flask stuff:
63
+ instance/
64
+ .webassets-cache
65
+
66
+ # Scrapy stuff:
67
+ .scrapy
68
+
69
+ # Sphinx documentation
70
+ docs/_build/
71
+
72
+ # PyBuilder
73
+ .pybuilder/
74
+ target/
75
+
76
+ # Jupyter Notebook
77
+ .ipynb_checkpoints
78
+
79
+ # IPython
80
+ profile_default/
81
+ ipython_config.py
82
+
83
+ # pyenv
84
+ # For a library or package, you might want to ignore these files since the code is
85
+ # intended to run in multiple environments; otherwise, check those in:
86
+ # .python-version
87
+
88
+ # pipenv
89
+ # According to pypa/pipenv#1255, pipenv should generally not be check into control.
90
+ # However, if you're deploying an application, you can change this to include Pipfile.lock:
91
+ #Pipfile.lock
92
+
93
+ # poetry
94
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
95
+ # This is especially true for applications, but for libraries it is also recommended.
96
+ #poetry.lock
97
+
98
+ # pdm
99
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
100
+ #pdm.lock
101
+
102
+ # virtualenv
103
+ .venv/
104
+ venv/
105
+ ENV/
106
+ env/
107
+ ./env/
108
+ ./venv/
109
+
110
+ # Spyder project settings
111
+ .spyderproject
112
+ .spyproject
113
+
114
+ # Rope project settings
115
+ .ropeproject
116
+
117
+ # mkdocs documentation
118
+ /site
119
+
120
+ # mypy
121
+ .mypy_cache/
122
+ .dmypy.json
123
+ dmypy.json
124
+
125
+ # Pyre type checker
126
+ .pyre/
127
+
128
+ # pytype static analyzer
129
+ .pytype/
130
+
131
+ # Cython debug symbols
132
+ cython_debug/
133
+
134
+ # IDEs
135
+ .idea/
136
+ .vscode/
137
+ *.swp
138
+ *.swo
139
+
140
+ # Local env files
141
+ .env
142
+ .env.sec
143
+ .env.local
144
+ .env.*.local
@@ -0,0 +1,189 @@
1
+ # 開発者ガイド
2
+
3
+ このドキュメントでは、`llmcapa` ライブラリの開発、拡張、およびメンテナンス方法について説明します。
4
+
5
+ ---
6
+
7
+ ## プロジェクト構成
8
+
9
+ ```
10
+ llmcapa/
11
+ ├── pyproject.toml # ビルド設定 (Hatchling / PEP 621)
12
+ ├── LICENSE # Apache License 2.0
13
+ ├── README.md # ユーザー向けドキュメント(英語)
14
+ ├── README.ja.md # ユーザー向けドキュメント(日本語)
15
+ ├── DEVELOP.md # 開発者ガイド(英語)
16
+ ├── DEVELOP.ja.md # 開発者ガイド(日本語)
17
+ ├── src/llmcapa/
18
+ │ ├── __init__.py # 公開APIのエントリーポイント
19
+ │ ├── models.py # 機能データクラスと機能評価
20
+ │ ├── registry.py # インメモリレジストリ、ロード、およびOpenRouter取得
21
+ │ ├── cli.py # コマンドラインインターフェース
22
+ │ └── data/ # 同梱されているオフライン機能データ (JSON)
23
+ │ ├── __init__.py
24
+ │ ├── openai.json
25
+ │ ├── anthropic.json
26
+ │ └── ...
27
+ └── tests/ # ユニットテスト (pytest)
28
+ ├── test_registry.py
29
+ ├── test_cache.py
30
+ └── test_advanced.py
31
+ ```
32
+
33
+ ---
34
+
35
+ ## 設計思想
36
+
37
+ 1. **オフラインファースト**: すべてのコア機能データは、パッケージ内にJSONファイルとして静的に同梱されています。標準的な検索時にネットワークリクエストは発生しません。
38
+ 2. **実行時依存関係ゼロ**: ライブラリはPython標準ライブラリのみで動作する必要があります。外部パッケージ(`pytest` や `build` など)は、開発およびテスト専用です。
39
+ 3. **不変性とパフォーマンス**: `Capability` データクラスは `frozen=True` です。機能チェック時の冗長な計算を避けるため、評価結果はメモ化(内部キャッシュ)されます。
40
+
41
+ ---
42
+
43
+ ## 新しいプロバイダーの追加
44
+
45
+ 新しいモデルプロバイダー(例: `cohere`)を追加する場合:
46
+
47
+ ### 1. データファイルの作成
48
+ `src/llmcapa/data/<provider_name>.json` に新しいJSONファイルを作成します。
49
+
50
+ ```json
51
+ {
52
+ "models": [
53
+ {
54
+ "provider": "cohere",
55
+ "model_id": "command-r-plus",
56
+ "display_name": "Command R+",
57
+ "context_window": 128000,
58
+ "max_output_tokens": 4000,
59
+ "input_modalities": ["text"],
60
+ "output_modalities": ["text"],
61
+ "supports_chat_completion": true,
62
+ "supports_function_calling": true,
63
+ "supports_json_mode": true,
64
+ "supports_streaming": true,
65
+ "supports_vision": false,
66
+ "supports_reasoning": false,
67
+ "tokenizer_name": "cohere-command",
68
+ "pricing": {
69
+ "input_per_1m": 2.5,
70
+ "output_per_1m": 10.0,
71
+ "currency": "USD"
72
+ },
73
+ "knowledge_cutoff": "2024-01",
74
+ "aliases": ["cohere/command-r-plus"]
75
+ }
76
+ ]
77
+ }
78
+ ```
79
+
80
+ ### 2. プロバイダーテストリストの更新
81
+ `tests/test_registry.py` を開き、`test_providers()` 内の `expected` セットに新しいプロバイダー名を追加します:
82
+
83
+ ```python
84
+ def test_providers():
85
+ provs = llmcapa.providers()
86
+ expected = {
87
+ "openai", "anthropic", "google",
88
+ "xai", "meta", "mistral", "qwen", "deepseek", "nvidia",
89
+ "microsoft", "amazon", "ntt", "customer-cloud", "elyza",
90
+ "softbank", "nec", "fujitsu", "pfn",
91
+ "cohere", # ここに追加
92
+ }
93
+ assert expected <= set(provs)
94
+ ```
95
+
96
+ ---
97
+
98
+ ## 新しい機能フラグの追加
99
+
100
+ 新しい機能フラグ(例: `supports_structured_outputs`)を追加する場合:
101
+
102
+ ### 1. データクラスの更新
103
+ `src/llmcapa/models.py` を開き、`Capability` データクラスにデフォルト値を持つ新しいフィールドを追加します:
104
+
105
+ ```python
106
+ @dataclass(frozen=True)
107
+ class Capability:
108
+ ...
109
+ supports_structured_outputs: bool = False
110
+ ...
111
+ ```
112
+
113
+ ### 2. 代替モデルチェッカーの更新(任意)
114
+ 追加する機能が、あるモデルが別のモデルを代替できるか検証する際に必須となる重要な機能である場合、`src/llmcapa/models.py` 内の `can_be_replaced_by()` の `features_to_check` リリストに追加します:
115
+
116
+ ```python
117
+ def can_be_replaced_by(self, other: "Capability", required_features: Optional[List[str]] = None) -> bool:
118
+ ...
119
+ if required_features is None:
120
+ features_to_check = [
121
+ "vision", "function_calling", "json_mode", "streaming",
122
+ "reasoning", "chat_completion", "responses_api",
123
+ "reasoning_effort", "thinking_budget", "image_output",
124
+ "audio_output", "video_output",
125
+ "structured_outputs" # ここに追加
126
+ ]
127
+ required_features = [f for f in features_to_check if self.supports(f)]
128
+ ...
129
+ ```
130
+
131
+ ### 3. JSONデータファイルの更新
132
+ `src/llmcapa/data/` 配下の関連するモデルのJSONファイルに、新しいフィールドを追加します。
133
+
134
+ ### 4. ユニットテストの追加
135
+ `tests/test_advanced.py` または `tests/test_registry.py` にテストケースを追加し、新しい機能フラグが正しくパース、評価、およびキャッシュされることを検証します。
136
+
137
+ ---
138
+
139
+ ## 開発ワークフロー
140
+
141
+ ### テストの実行
142
+ テストには `pytest` を使用します。プロジェクトのルートディレクトリから以下のコマンドを実行します:
143
+
144
+ ```bash
145
+ # PYTHONPATHにsrcディレクトリを追加
146
+ set "PYTHONPATH=src;%PYTHONPATH%"
147
+ python -m pytest -v
148
+ ```
149
+
150
+ ### コードの検証
151
+ ビルドやコミットを行う前に、すべてのPythonファイルが正常にコンパイルできるか確認します:
152
+
153
+ ```bash
154
+ python -m py_compile src/llmcapa/*.py tests/*.py
155
+ ```
156
+
157
+ ### パッケージのビルド
158
+ ソース配布物(sdist)とwheelバイナリをビルドする場合:
159
+
160
+ ```bash
161
+ # ビルド依存関係がインストールされていない場合はインストール
162
+ pip install build hatchling
163
+
164
+ # パッケージをビルド
165
+ python -m build
166
+ ```
167
+
168
+ ビルドされたファイルは `dist/` ディレクトリ配下に生成されます。
169
+
170
+ ---
171
+
172
+ ## OpenRouter マッピング詳細
173
+
174
+ `fetch_openrouter()` が呼び出されると、OpenRouter APIのモデルスキーマは以下のように `Capability` データクラスにマッピングされます:
175
+
176
+ | 機能フィールド | OpenRouter API フィールド | マッピングロジック / フォールバック |
177
+ |---|---|---|
178
+ | `model_id` | `id` | 完全一致 |
179
+ | `display_name` | `name` | 存在しない場合は `id` にフォールバック |
180
+ | `context_window` | `context_length` | `int` にキャスト、デフォルトは `0` |
181
+ | `max_output_tokens` | `top_provider.max_completion_tokens` | `int` にキャスト、デフォルトは `0` |
182
+ | `input_modalities` | `architecture.input_modalities` | デフォルトは `["text"]` |
183
+ | `output_modalities` | `architecture.output_modalities` | デフォルトは `["text"]` |
184
+ | `supports_function_calling` | `supported_parameters` | `"tools"` または `"tool_choice"` が存在すれば `True` |
185
+ | `supports_json_mode` | `supported_parameters` | `"structured_outputs"` または `"response_format"` が存在すれば `True` |
186
+ | `supports_reasoning` | `supported_parameters` | `"reasoning"` または `"include_reasoning"` が存在すれば `True` |
187
+ | `supports_reasoning_effort` | `supported_parameters` | `"reasoning"` が存在すれば `True` |
188
+ | `pricing` | `pricing` | `prompt` と `completion` のレートを100万トークンあたりのレートに変換 |
189
+ | `aliases` | `id` | 小文字に変換された `id` がエイリアスとして追加されます |
@@ -0,0 +1,187 @@
1
+ # Developer Guide
2
+
3
+ This document explains how to develop, extend, and maintain the `llmcapa` library.
4
+
5
+ ---
6
+
7
+ ## Project Structure
8
+
9
+ ```
10
+ llmcapa/
11
+ ├── pyproject.toml # Build configuration (Hatchling / PEP 621)
12
+ ├── LICENSE # Apache License 2.0
13
+ ├── README.md # User documentation
14
+ ├── DEVELOP.md # This guide
15
+ ├── src/llmcapa/
16
+ │ ├── __init__.py # Public API entry point
17
+ │ ├── models.py # Capability dataclass and feature evaluation
18
+ │ ├── registry.py # In-memory registry, loading, and OpenRouter fetching
19
+ │ ├── cli.py # Command-line interface
20
+ │ └── data/ # Bundled offline capability data (JSON)
21
+ │ ├── __init__.py
22
+ │ ├── openai.json
23
+ │ ├── anthropic.json
24
+ │ └── ...
25
+ └── tests/ # Unit tests (pytest)
26
+ ├── test_registry.py
27
+ ├── test_cache.py
28
+ └── test_advanced.py
29
+ ```
30
+
31
+ ---
32
+
33
+ ## Design Philosophy
34
+
35
+ 1. **Offline-First**: All core capability data is bundled statically inside the package as JSON files. No network requests are made during standard lookups.
36
+ 2. **Zero Runtime Dependencies**: The library must run using only the Python standard library. External packages (like `pytest` or `build`) are strictly for development/testing.
37
+ 3. **Immutability & Performance**: The `Capability` dataclass is `frozen=True`. To avoid redundant calculations during feature checks, evaluation results are cached internally using memoization.
38
+
39
+ ---
40
+
41
+ ## Adding a New Provider
42
+
43
+ To add a new model provider (e.g., `cohere`):
44
+
45
+ ### 1. Create a Data File
46
+ Create a new JSON file under `src/llmcapa/data/<provider_name>.json`.
47
+
48
+ ```json
49
+ {
50
+ "models": [
51
+ {
52
+ "provider": "cohere",
53
+ "model_id": "command-r-plus",
54
+ "display_name": "Command R+",
55
+ "context_window": 128000,
56
+ "max_output_tokens": 4000,
57
+ "input_modalities": ["text"],
58
+ "output_modalities": ["text"],
59
+ "supports_chat_completion": true,
60
+ "supports_function_calling": true,
61
+ "supports_json_mode": true,
62
+ "supports_streaming": true,
63
+ "supports_vision": false,
64
+ "supports_reasoning": false,
65
+ "tokenizer_name": "cohere-command",
66
+ "pricing": {
67
+ "input_per_1m": 2.5,
68
+ "output_per_1m": 10.0,
69
+ "currency": "USD"
70
+ },
71
+ "knowledge_cutoff": "2024-01",
72
+ "aliases": ["cohere/command-r-plus"]
73
+ }
74
+ ]
75
+ }
76
+ ```
77
+
78
+ ### 2. Update the Provider Test List
79
+ Open `tests/test_registry.py` and add your new provider name to the `expected` set in `test_providers()`:
80
+
81
+ ```python
82
+ def test_providers():
83
+ provs = llmcapa.providers()
84
+ expected = {
85
+ "openai", "anthropic", "google",
86
+ "xai", "meta", "mistral", "qwen", "deepseek", "nvidia",
87
+ "microsoft", "amazon", "ntt", "customer-cloud", "elyza",
88
+ "softbank", "nec", "fujitsu", "pfn",
89
+ "cohere", # Add here
90
+ }
91
+ assert expected <= set(provs)
92
+ ```
93
+
94
+ ---
95
+
96
+ ## Adding a New Feature Flag
97
+
98
+ To add a new capability/feature flag (e.g., `supports_structured_outputs`):
99
+
100
+ ### 1. Update the Dataclass
101
+ Open `src/llmcapa/models.py` and add the new field to the `Capability` dataclass with a default value:
102
+
103
+ ```python
104
+ @dataclass(frozen=True)
105
+ class Capability:
106
+ ...
107
+ supports_structured_outputs: bool = False
108
+ ...
109
+ ```
110
+
111
+ ### 2. Update the Replacement Checker (Optional)
112
+ If the new feature is a critical capability that should be verified when checking if one model can replace another, add it to the `features_to_check` list in `can_be_replaced_by()` inside `src/llmcapa/models.py`:
113
+
114
+ ```python
115
+ def can_be_replaced_by(self, other: "Capability", required_features: Optional[List[str]] = None) -> bool:
116
+ ...
117
+ if required_features is None:
118
+ features_to_check = [
119
+ "vision", "function_calling", "json_mode", "streaming",
120
+ "reasoning", "chat_completion", "responses_api",
121
+ "reasoning_effort", "thinking_budget", "image_output",
122
+ "audio_output", "video_output",
123
+ "structured_outputs" # Add here
124
+ ]
125
+ required_features = [f for f in features_to_check if self.supports(f)]
126
+ ...
127
+ ```
128
+
129
+ ### 3. Update JSON Data Files
130
+ Add the new field to the relevant models in the JSON files under `src/llmcapa/data/`.
131
+
132
+ ### 4. Add Unit Tests
133
+ Add test cases in `tests/test_advanced.py` or `tests/test_registry.py` to verify that the new feature flag is correctly parsed, evaluated, and cached.
134
+
135
+ ---
136
+
137
+ ## Development Workflow
138
+
139
+ ### Running Tests
140
+ We use `pytest` for testing. Run the following command from the project root directory:
141
+
142
+ ```bash
143
+ # Set PYTHONPATH to include the src directory
144
+ set "PYTHONPATH=src;%PYTHONPATH%"
145
+ python -m pytest -v
146
+ ```
147
+
148
+ ### Code Verification
149
+ Before building or committing, verify that all Python files compile successfully:
150
+
151
+ ```bash
152
+ python -m py_compile src/llmcapa/*.py tests/*.py
153
+ ```
154
+
155
+ ### Building the Package
156
+ To build the source distribution (sdist) and wheel binary:
157
+
158
+ ```bash
159
+ # Install build dependencies if not already installed
160
+ pip install build hatchling
161
+
162
+ # Build the package
163
+ python -m build
164
+ ```
165
+
166
+ The built files will be generated under the `dist/` directory.
167
+
168
+ ---
169
+
170
+ ## OpenRouter Mapping Details
171
+
172
+ When `fetch_openrouter()` is called, it maps the OpenRouter API model schema to our `Capability` dataclass as follows:
173
+
174
+ | Capability Field | OpenRouter API Field | Mapping Logic / Fallback |
175
+ |---|---|---|
176
+ | `model_id` | `id` | Exact match |
177
+ | `display_name` | `name` | Falls back to `id` if missing |
178
+ | `context_window` | `context_length` | Cast to `int`, default `0` |
179
+ | `max_output_tokens` | `top_provider.max_completion_tokens` | Cast to `int`, default `0` |
180
+ | `input_modalities` | `architecture.input_modalities` | Default `["text"]` |
181
+ | `output_modalities` | `architecture.output_modalities` | Default `["text"]` |
182
+ | `supports_function_calling` | `supported_parameters` | `True` if `"tools"` or `"tool_choice"` is present |
183
+ | `supports_json_mode` | `supported_parameters` | `True` if `"structured_outputs"` or `"response_format"` is present |
184
+ | `supports_reasoning` | `supported_parameters` | `True` if `"reasoning"` or `"include_reasoning"` is present |
185
+ | `supports_reasoning_effort` | `supported_parameters` | `True` if `"reasoning"` is present |
186
+ | `pricing` | `pricing` | Converts `prompt` and `completion` rates to per-1M token rates |
187
+ | `aliases` | `id` | Lowercased `id` is added as an alias |