chllm 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.
Files changed (39) hide show
  1. chllm-0.1.0/.github/workflows/ci.yml +44 -0
  2. chllm-0.1.0/.gitignore +36 -0
  3. chllm-0.1.0/LICENSE +21 -0
  4. chllm-0.1.0/PKG-INFO +172 -0
  5. chllm-0.1.0/README.md +154 -0
  6. chllm-0.1.0/antigravity.md +30 -0
  7. chllm-0.1.0/examples/orchestration_demo.py +61 -0
  8. chllm-0.1.0/examples/recovery_demo.py +51 -0
  9. chllm-0.1.0/pyproject.toml +70 -0
  10. chllm-0.1.0/src/chllm/__init__.py +39 -0
  11. chllm-0.1.0/src/chllm/antigravity.md +30 -0
  12. chllm-0.1.0/src/chllm/builder.py +89 -0
  13. chllm-0.1.0/src/chllm/context.py +83 -0
  14. chllm-0.1.0/src/chllm/exceptions/__init__.py +25 -0
  15. chllm-0.1.0/src/chllm/exceptions/base.py +5 -0
  16. chllm-0.1.0/src/chllm/exceptions/parsing.py +11 -0
  17. chllm-0.1.0/src/chllm/exceptions/provider.py +34 -0
  18. chllm-0.1.0/src/chllm/masking.py +119 -0
  19. chllm-0.1.0/src/chllm/metrics.py +122 -0
  20. chllm-0.1.0/src/chllm/orchestrator.py +293 -0
  21. chllm-0.1.0/src/chllm/parser.py +468 -0
  22. chllm-0.1.0/src/chllm/py.typed +1 -0
  23. chllm-0.1.0/src/chllm/utils.py +24 -0
  24. chllm-0.1.0/tests/__init__.py +0 -0
  25. chllm-0.1.0/tests/test_agent_orchestrator.py +54 -0
  26. chllm-0.1.0/tests/test_batch_utils.py +22 -0
  27. chllm-0.1.0/tests/test_builder.py +72 -0
  28. chllm-0.1.0/tests/test_context.py +38 -0
  29. chllm-0.1.0/tests/test_exceptions.py +25 -0
  30. chllm-0.1.0/tests/test_masking.py +93 -0
  31. chllm-0.1.0/tests/test_metrics.py +53 -0
  32. chllm-0.1.0/tests/test_orchestrator.py +80 -0
  33. chllm-0.1.0/tests/test_orchestrator_single.py +48 -0
  34. chllm-0.1.0/tests/test_parser.py +80 -0
  35. chllm-0.1.0/tests/test_parser_robustness.py +42 -0
  36. chllm-0.1.0/tests/test_parser_tools.py +91 -0
  37. chllm-0.1.0/tests/test_parser_verification.py +40 -0
  38. chllm-0.1.0/tests/test_prompt_hierarchy.py +20 -0
  39. chllm-0.1.0/uv.lock +1222 -0
@@ -0,0 +1,44 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [ main, master ]
6
+ pull_request:
7
+ branches: [ main, master ]
8
+
9
+ jobs:
10
+ ci:
11
+ runs-on: ubuntu-latest
12
+ strategy:
13
+ matrix:
14
+ python-version: ["3.10", "3.11", "3.12", "3.13"]
15
+ steps:
16
+ - name: Checkout code
17
+ uses: actions/checkout@v4
18
+
19
+ - name: Install uv
20
+ uses: astral-sh/setup-uv@v3
21
+ with:
22
+ enable-cache: true
23
+ cache-dependency-glob: "uv.lock"
24
+
25
+ - name: Set up Python ${{ matrix.python-version }}
26
+ run: uv python install ${{ matrix.python-version }}
27
+
28
+ - name: Install dependencies
29
+ run: uv sync
30
+
31
+ - name: Run Ruff check
32
+ run: uv run ruff check .
33
+
34
+ - name: Run Ruff format check
35
+ run: uv run ruff format --check .
36
+
37
+ - name: Run Mypy
38
+ run: uv run mypy .
39
+
40
+ - name: Run chutils dev ai-lint
41
+ run: uv run chutils dev ai-lint
42
+
43
+ - name: Run tests with pytest
44
+ run: uv run pytest
chllm-0.1.0/.gitignore ADDED
@@ -0,0 +1,36 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # Distribution / packaging
7
+ build/
8
+ dist/
9
+ *.egg-info/
10
+ .eggs/
11
+
12
+ # Environments
13
+ .venv/
14
+ env/
15
+ venv/
16
+ ENV/
17
+
18
+ # Testing & Coverage
19
+ .pytest_cache/
20
+ .coverage
21
+ .coverage.*
22
+ htmlcov/
23
+
24
+ # Type Checking & Linters
25
+ .mypy_cache/
26
+ .ruff_cache/
27
+
28
+ # IDEs
29
+ .idea/
30
+ .vscode/
31
+ *.swp
32
+ *.swo
33
+
34
+ # Project specific
35
+ logs/
36
+ *.log
chllm-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Chu4hel
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
chllm-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,172 @@
1
+ Metadata-Version: 2.5
2
+ Name: chllm
3
+ Version: 0.1.0
4
+ Summary: Отказоустойчивый Python фреймворк для взаимодействия с LLM, валидации Pydantic и надежного парсинга структурированных ответов.
5
+ Author-email: Chu4hel <sergeiivanov636@gmail.com>
6
+ License-Expression: MIT
7
+ License-File: LICENSE
8
+ Requires-Python: >=3.10
9
+ Requires-Dist: pydantic>=2.8.0
10
+ Provides-Extra: all
11
+ Requires-Dist: chutils>=3.5.0; extra == 'all'
12
+ Requires-Dist: tiktoken>=0.7.0; extra == 'all'
13
+ Provides-Extra: chutils
14
+ Requires-Dist: chutils>=3.5.0; extra == 'chutils'
15
+ Provides-Extra: tokens
16
+ Requires-Dist: tiktoken>=0.7.0; extra == 'tokens'
17
+ Description-Content-Type: text/markdown
18
+
19
+ # chllm: Robust Structured Data Framework for LLMs
20
+
21
+ [![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
22
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
23
+
24
+ `chllm` (произносится *chill-em*) — это профессиональный легковесный Python-фреймворк для построения отказоустойчивых конвейеров обработки данных через LLM. Библиотека специализируется на извлечении структурированных ответов (JSON / Pydantic) в условиях нестабильных API, обрывов контекста и жестких лимитов провайдеров.
25
+
26
+ ---
27
+
28
+ ## 🚀 Почему chllm?
29
+
30
+ Работа с LLM в реальных приложениях сопряжена с рядом проблем:
31
+ - **Обрезанные ответы**: модели часто не успевают закрыть скобки/кавычки JSON из-за лимита токенов.
32
+ - **Галлюцинации синтаксиса**: ИИ может непреднамеренно перевести или сломать переменные, плейсхолдеры и теги.
33
+ - **Сложные ошибки и Rate Limits**: ретраи для ошибок 429, 503 и фильтрации контента требуют принципиально разной обработки.
34
+ - **Агентные циклы**: необходимость надежно парсить вызовы инструментов (Tool Calls) и управлять шагами выполнения.
35
+
36
+ `chllm` берет всю эту рутину на себя.
37
+
38
+ ---
39
+
40
+ ## 📦 Установка
41
+
42
+ ```bash
43
+ # Базовая установка (только Pydantic)
44
+ pip install chllm
45
+ # или через uv
46
+ uv add chllm
47
+
48
+ # С расширенным логированием через chutils
49
+ uv add "chllm[chutils]"
50
+
51
+ # С точным подсчетом токенов через tiktoken
52
+ uv add "chllm[tokens]"
53
+
54
+ # Полный набор
55
+ uv add "chllm[all]"
56
+ ```
57
+
58
+ ---
59
+
60
+ ## 🛠 Ключевые модули
61
+
62
+ ### 1. RobustLLMParser (`chllm.parser`)
63
+ Интеллектуальный парсер, способный извлекать и восстанавливать данные даже из поврежденных ответов:
64
+ - **Стековое восстановление (Deep Recovery)**: автоматически достраивает незакрытые скобки, кавычки и массивы в оборванном JSON.
65
+ - **Извлечение из Markdown**: находит JSON-блоки внутри пояснительного текста или рассуждений модели.
66
+ - **JSON Lines Fallback**: если модель прислала поток несоединенных JSON-объектов, парсер автоматически объединит их в единый список/батч.
67
+ - **Интеграция с Pydantic**: строгая валидация и приведение к типам моделей на лету.
68
+ - **Tool Use Parsing**: метод `parse_tool_calls` находит структурированные вызовы инструментов.
69
+
70
+ ### 2. Orchestrator & AgentOrchestrator (`chllm.orchestrator`)
71
+ Двигатель выполнения запросов с адаптивным поведением:
72
+ - **Бинарное деление батчей (Batch Splitting)**: при возникновении ошибок размера или цензуры рекурсивно делит батч, изолируя сбойный элемент.
73
+ - **Умная стратегия повторов (RetryStrategy)**: экспоненциальная задержка с рандомизированным джиттером для защиты от перегрузки API.
74
+ - **Одиночные запросы**: метод `execute_single(prompt)` для удобного выполнения утилитарных задач.
75
+ - **Агентный цикл (`AgentOrchestrator`)**: метод `execute_loop` берет на себя цикл "запрос -> парсинг инструментов -> выполнение -> возврат результата".
76
+
77
+ ### 3. ContentMasker (`chllm.masking`)
78
+ Защита системного синтаксиса и чувствительных участков текста:
79
+ - Маскирует переменные (например, `[MCname]`, `%(user)s`, `{b}...{/b}`) в плейсхолдеры вида `[[[VAR_0]]]`.
80
+ - Модель видит структуру предложения, но физически не может повредить или перевести системные теги.
81
+ - Корректная сортировка паттернов по длине для предотвращения коллизий.
82
+
83
+ ### 4. Metrics & Token Estimation (`chllm.metrics`)
84
+ Контроль расхода токенов:
85
+ - `TokenCounter`: поддержка эвристического расчета для русского и английского языков, а также токенизатора `tiktoken`.
86
+ - `estimate_completion_tokens`: прогнозирование объема ответа с учетом коэффициента языкового расширения и оверхеда схемы.
87
+
88
+ ### 5. Context & Prompt Builders (`chllm.builder`, `chllm.context`)
89
+ - `PromptBuilder`: динамическая сборка системных промптов, контекста и пользовательских полезных нагрузок.
90
+ - `ContextBuilder`: управление скользящей цепочкой контекста диалогов (Chain Context).
91
+
92
+ ---
93
+
94
+ ## 📖 Быстрый старт
95
+
96
+ ### Восстановление поврежденного JSON
97
+
98
+ ```python
99
+ from pydantic import BaseModel
100
+ from chllm import RobustLLMParser
101
+
102
+
103
+ class UserItem(BaseModel):
104
+ id: int
105
+ name: str
106
+
107
+
108
+ parser = RobustLLMParser()
109
+
110
+ # Модель оборвала ответ на середине:
111
+ broken_response = """
112
+ Вот результаты:
113
+ ```json
114
+ [
115
+ {"id": 1, "name": "Алиса"},
116
+ {"id": 2, "name": "Борис"
117
+ """
118
+
119
+ data = parser.parse(broken_response, validation_model=UserItem)
120
+ # data["batch"] -> [UserItem(id=1, name="Алиса")]
121
+ ```
122
+
123
+ ### Защита переменных при переводе / рерайте
124
+
125
+ ```python
126
+ from chllm import ContentMasker
127
+
128
+ masker = ContentMasker(patterns=[r"\[.+?\]", r"\{.+?\}"])
129
+ text = "Привет, [player_name]! Нажми {b}Старт{/b}."
130
+
131
+ masked = masker.mask(text)
132
+ # masked.masked_text -> "Привет, [[[VAR_0]]]! Нажми [[[VAR_1]]]Старт[[[VAR_2]]]."
133
+
134
+ # Отправляем masked.masked_text в LLM и получаем "Hello, [[[VAR_0]]]! Press [[[VAR_1]]]Start[[[VAR_2]]]."
135
+
136
+ demasked = masker.demask(translated_text, masked.mapping)
137
+ # demasked -> "Hello, [player_name]! Press {b}Start{/b}."
138
+ ```
139
+
140
+ ### Оркестратор запросов с ретраями
141
+
142
+ ```python
143
+ from chllm import Orchestrator, RetryStrategy, RateLimitError
144
+
145
+
146
+ class MyLLMProvider:
147
+ async def execute(self, payload: str) -> str:
148
+ # Ваш сетевой вызов к API модели
149
+ return await api_client.generate(payload)
150
+
151
+
152
+ orchestrator = Orchestrator(
153
+ provider=MyLLMProvider(),
154
+ strategy=RetryStrategy(max_retries=3, base_delay=1.5),
155
+ )
156
+
157
+ response = await orchestrator.execute_single("Объясни квантовую запутанность кратко.")
158
+ ```
159
+
160
+ ---
161
+
162
+ ## 🏗 Архитектура
163
+
164
+ Библиотека строго следует принципу **Dependency Inversion**:
165
+ - Модули не привязаны к конкретным внешним SDK (Google GenAI, OpenAI, Anthropic) — взаимодействие построено через протоколы.
166
+ - Логирование автономно: при наличии `chutils` используется его структурированный логгер, иначе — стандартный `logging`.
167
+
168
+ ---
169
+
170
+ ## 📄 Лицензия
171
+
172
+ Распространяется под лицензией [MIT](LICENSE).
chllm-0.1.0/README.md ADDED
@@ -0,0 +1,154 @@
1
+ # chllm: Robust Structured Data Framework for LLMs
2
+
3
+ [![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
+
6
+ `chllm` (произносится *chill-em*) — это профессиональный легковесный Python-фреймворк для построения отказоустойчивых конвейеров обработки данных через LLM. Библиотека специализируется на извлечении структурированных ответов (JSON / Pydantic) в условиях нестабильных API, обрывов контекста и жестких лимитов провайдеров.
7
+
8
+ ---
9
+
10
+ ## 🚀 Почему chllm?
11
+
12
+ Работа с LLM в реальных приложениях сопряжена с рядом проблем:
13
+ - **Обрезанные ответы**: модели часто не успевают закрыть скобки/кавычки JSON из-за лимита токенов.
14
+ - **Галлюцинации синтаксиса**: ИИ может непреднамеренно перевести или сломать переменные, плейсхолдеры и теги.
15
+ - **Сложные ошибки и Rate Limits**: ретраи для ошибок 429, 503 и фильтрации контента требуют принципиально разной обработки.
16
+ - **Агентные циклы**: необходимость надежно парсить вызовы инструментов (Tool Calls) и управлять шагами выполнения.
17
+
18
+ `chllm` берет всю эту рутину на себя.
19
+
20
+ ---
21
+
22
+ ## 📦 Установка
23
+
24
+ ```bash
25
+ # Базовая установка (только Pydantic)
26
+ pip install chllm
27
+ # или через uv
28
+ uv add chllm
29
+
30
+ # С расширенным логированием через chutils
31
+ uv add "chllm[chutils]"
32
+
33
+ # С точным подсчетом токенов через tiktoken
34
+ uv add "chllm[tokens]"
35
+
36
+ # Полный набор
37
+ uv add "chllm[all]"
38
+ ```
39
+
40
+ ---
41
+
42
+ ## 🛠 Ключевые модули
43
+
44
+ ### 1. RobustLLMParser (`chllm.parser`)
45
+ Интеллектуальный парсер, способный извлекать и восстанавливать данные даже из поврежденных ответов:
46
+ - **Стековое восстановление (Deep Recovery)**: автоматически достраивает незакрытые скобки, кавычки и массивы в оборванном JSON.
47
+ - **Извлечение из Markdown**: находит JSON-блоки внутри пояснительного текста или рассуждений модели.
48
+ - **JSON Lines Fallback**: если модель прислала поток несоединенных JSON-объектов, парсер автоматически объединит их в единый список/батч.
49
+ - **Интеграция с Pydantic**: строгая валидация и приведение к типам моделей на лету.
50
+ - **Tool Use Parsing**: метод `parse_tool_calls` находит структурированные вызовы инструментов.
51
+
52
+ ### 2. Orchestrator & AgentOrchestrator (`chllm.orchestrator`)
53
+ Двигатель выполнения запросов с адаптивным поведением:
54
+ - **Бинарное деление батчей (Batch Splitting)**: при возникновении ошибок размера или цензуры рекурсивно делит батч, изолируя сбойный элемент.
55
+ - **Умная стратегия повторов (RetryStrategy)**: экспоненциальная задержка с рандомизированным джиттером для защиты от перегрузки API.
56
+ - **Одиночные запросы**: метод `execute_single(prompt)` для удобного выполнения утилитарных задач.
57
+ - **Агентный цикл (`AgentOrchestrator`)**: метод `execute_loop` берет на себя цикл "запрос -> парсинг инструментов -> выполнение -> возврат результата".
58
+
59
+ ### 3. ContentMasker (`chllm.masking`)
60
+ Защита системного синтаксиса и чувствительных участков текста:
61
+ - Маскирует переменные (например, `[MCname]`, `%(user)s`, `{b}...{/b}`) в плейсхолдеры вида `[[[VAR_0]]]`.
62
+ - Модель видит структуру предложения, но физически не может повредить или перевести системные теги.
63
+ - Корректная сортировка паттернов по длине для предотвращения коллизий.
64
+
65
+ ### 4. Metrics & Token Estimation (`chllm.metrics`)
66
+ Контроль расхода токенов:
67
+ - `TokenCounter`: поддержка эвристического расчета для русского и английского языков, а также токенизатора `tiktoken`.
68
+ - `estimate_completion_tokens`: прогнозирование объема ответа с учетом коэффициента языкового расширения и оверхеда схемы.
69
+
70
+ ### 5. Context & Prompt Builders (`chllm.builder`, `chllm.context`)
71
+ - `PromptBuilder`: динамическая сборка системных промптов, контекста и пользовательских полезных нагрузок.
72
+ - `ContextBuilder`: управление скользящей цепочкой контекста диалогов (Chain Context).
73
+
74
+ ---
75
+
76
+ ## 📖 Быстрый старт
77
+
78
+ ### Восстановление поврежденного JSON
79
+
80
+ ```python
81
+ from pydantic import BaseModel
82
+ from chllm import RobustLLMParser
83
+
84
+
85
+ class UserItem(BaseModel):
86
+ id: int
87
+ name: str
88
+
89
+
90
+ parser = RobustLLMParser()
91
+
92
+ # Модель оборвала ответ на середине:
93
+ broken_response = """
94
+ Вот результаты:
95
+ ```json
96
+ [
97
+ {"id": 1, "name": "Алиса"},
98
+ {"id": 2, "name": "Борис"
99
+ """
100
+
101
+ data = parser.parse(broken_response, validation_model=UserItem)
102
+ # data["batch"] -> [UserItem(id=1, name="Алиса")]
103
+ ```
104
+
105
+ ### Защита переменных при переводе / рерайте
106
+
107
+ ```python
108
+ from chllm import ContentMasker
109
+
110
+ masker = ContentMasker(patterns=[r"\[.+?\]", r"\{.+?\}"])
111
+ text = "Привет, [player_name]! Нажми {b}Старт{/b}."
112
+
113
+ masked = masker.mask(text)
114
+ # masked.masked_text -> "Привет, [[[VAR_0]]]! Нажми [[[VAR_1]]]Старт[[[VAR_2]]]."
115
+
116
+ # Отправляем masked.masked_text в LLM и получаем "Hello, [[[VAR_0]]]! Press [[[VAR_1]]]Start[[[VAR_2]]]."
117
+
118
+ demasked = masker.demask(translated_text, masked.mapping)
119
+ # demasked -> "Hello, [player_name]! Press {b}Start{/b}."
120
+ ```
121
+
122
+ ### Оркестратор запросов с ретраями
123
+
124
+ ```python
125
+ from chllm import Orchestrator, RetryStrategy, RateLimitError
126
+
127
+
128
+ class MyLLMProvider:
129
+ async def execute(self, payload: str) -> str:
130
+ # Ваш сетевой вызов к API модели
131
+ return await api_client.generate(payload)
132
+
133
+
134
+ orchestrator = Orchestrator(
135
+ provider=MyLLMProvider(),
136
+ strategy=RetryStrategy(max_retries=3, base_delay=1.5),
137
+ )
138
+
139
+ response = await orchestrator.execute_single("Объясни квантовую запутанность кратко.")
140
+ ```
141
+
142
+ ---
143
+
144
+ ## 🏗 Архитектура
145
+
146
+ Библиотека строго следует принципу **Dependency Inversion**:
147
+ - Модули не привязаны к конкретным внешним SDK (Google GenAI, OpenAI, Anthropic) — взаимодействие построено через протоколы.
148
+ - Логирование автономно: при наличии `chutils` используется его структурированный логгер, иначе — стандартный `logging`.
149
+
150
+ ---
151
+
152
+ ## 📄 Лицензия
153
+
154
+ Распространяется под лицензией [MIT](LICENSE).
@@ -0,0 +1,30 @@
1
+ # Манифест ИИ: chllm (Robust LLM Framework)
2
+
3
+ Модуль chllm представляет собой отказоустойчивый фреймворк для взаимодействия с LLM-провайдерами, управления контекстом промптов и надежного парсинга структурированных ответов.
4
+
5
+ ## Назначение и Архитектура
6
+
7
+ Модуль изолирует работу с нейросетевыми моделями от доменной логики приложения.
8
+
9
+ ### Ключевые компоненты:
10
+
11
+ 1. **RobustLLMParser (parser.py)**:
12
+ - Извлечение JSON, Markdown и очистка ответа от технического шума LLM.
13
+ - Восстановление поврежденного JSON и валидация схем Pydantic.
14
+
15
+ 2. **Orchestrator, AgentOrchestrator (orchestrator.py)**:
16
+ - Управление ротацией API-ключей и прокси.
17
+ - Стратегии повторных попыток (RetryStrategy) с экспоненциальной задержкой.
18
+
19
+ 3. **ContentMasker (masking.py)**:
20
+ - Маскирование и защитная подстановка чувствительных данных и тегов Ren'Py перед отправкой в LLM.
21
+
22
+ 4. **PromptBuilder, ContextBuilder (uilder.py, context.py)**:
23
+ - Динамическая сборка системных и пользовательских промптов с ограничением по токенам.
24
+
25
+ 5. **TokenCounter, UsageMetrics (metrics.py)**:
26
+ - Подсчет токенов и сбор статистики использования API.
27
+
28
+ ## Правила использования
29
+ - При работе с ответами LLM всегда использовать RobustLLMParser.
30
+ - Ошибки LLM обрабатывать через иерархию CHLLMError (например, RateLimitError, QuotaExceededError).
@@ -0,0 +1,61 @@
1
+ """
2
+ Демонстрация работы Orchestrator: деление батча и ретраи.
3
+ """
4
+
5
+ import asyncio
6
+
7
+ from chllm import ContentBlockedError, Orchestrator, RateLimitError, RetryStrategy
8
+
9
+
10
+ class FakeAIProvider:
11
+ """Мок-провайдер, имитирующий проблемы с лимитами и цензурой."""
12
+
13
+ def __init__(self) -> None:
14
+ """Инициализирует тестовый провайдер."""
15
+ self.attempts: int = 0
16
+
17
+ async def execute(self, data: object) -> object:
18
+ """Выполняет имитацию запроса к ИИ.
19
+
20
+ Args:
21
+ data: Данные для обработки.
22
+
23
+ Returns:
24
+ Результат обработки.
25
+ """
26
+ self.attempts += 1
27
+
28
+ # 1. Имитируем временный лимит на первую попытку
29
+ if self.attempts == 1:
30
+ print("Попытка 1: Имитируем Rate Limit...")
31
+ raise RateLimitError("Rate limit exceeded", retry_delay=0.1)
32
+
33
+ # 2. Имитируем блокировку контента для больших батчей
34
+ if isinstance(data, list) and len(data) > 1:
35
+ print(f"Батч из {len(data)} элементов заблокирован цензурой. Требуется деление!")
36
+ raise ContentBlockedError("Sensitive content detected")
37
+
38
+ print(f"Успешное выполнение для данных: {data}")
39
+ return f"OK: {data}"
40
+
41
+ def pack_single_prompt(self, prompt: str) -> object:
42
+ """Упаковывает строку промпта."""
43
+ return prompt
44
+
45
+
46
+ async def run_demo() -> None:
47
+ """Запускает демонстрацию работы оркестратора с обработкой ошибок."""
48
+ provider = FakeAIProvider()
49
+ orchestrator = Orchestrator(provider=provider, strategy=RetryStrategy(max_retries=3, base_delay=0.1))
50
+
51
+ print("--- Запуск оркестратора для батча из 3-х элементов ---")
52
+ # Оркестратор сделает ретрай при первой ошибке,
53
+ # а затем поделит батч, пока не найдет безопасные части.
54
+ results = await orchestrator.execute(["Safe 1", "Safe 2", "Safe 3"])
55
+
56
+ print("\n--- Финальные результаты ---")
57
+ print(results)
58
+
59
+
60
+ if __name__ == "__main__":
61
+ asyncio.run(run_demo())
@@ -0,0 +1,51 @@
1
+ """
2
+ Пример использования RobustLLMParser для восстановления поврежденного JSON.
3
+ """
4
+
5
+ from pydantic import BaseModel
6
+
7
+ from chllm import RobustLLMParser
8
+
9
+
10
+ class Product(BaseModel):
11
+ """Модель данных товара для демонстрации парсинга."""
12
+
13
+ name: str
14
+ price: float
15
+
16
+
17
+ def run_demo() -> None:
18
+ """Запускает демонстрацию восстановления поврежденного JSON ответа."""
19
+ parser = RobustLLMParser()
20
+
21
+ # Пример 1: ИИ обрезал ответ на середине
22
+ raw_response = """
23
+ Вот список товаров в формате JSON:
24
+ ```json
25
+ [
26
+ {"name": "Laptop", "price": 999.99},
27
+ {"name": "Smartphone", "price": 49
28
+ """ # JSON не закрыт, кавычка оборвана
29
+
30
+ print("--- Исходный текст ---")
31
+ print(raw_response)
32
+
33
+ result = parser.parse(raw_response, validation_model=Product)
34
+
35
+ print("\n--- Результат парсинга (бач) ---")
36
+ for item in result["batch"]:
37
+ if isinstance(item, Product):
38
+ print(f"Товар: {item.name}, Цена: {item.price}")
39
+ else:
40
+ print(f"Товар: {item.get('name')}, Цена: {item.get('price')}")
41
+
42
+ # Пример 2: Глубокая вложенность
43
+ nested_raw = '{"data": {"user": {"id": 1, "meta": {"bio": "Hello'
44
+ raw_obj = parser.parse_raw(nested_raw)
45
+
46
+ print("\n--- Восстановление вложенного объекта ---")
47
+ print(f"Полученный объект: {raw_obj}")
48
+
49
+
50
+ if __name__ == "__main__":
51
+ run_demo()
@@ -0,0 +1,70 @@
1
+ [project]
2
+ name = "chllm"
3
+ version = "0.1.0"
4
+ description = "Отказоустойчивый Python фреймворк для взаимодействия с LLM, валидации Pydantic и надежного парсинга структурированных ответов."
5
+ authors = [{ name = "Chu4hel", email = "sergeiivanov636@gmail.com" }]
6
+ license = "MIT"
7
+ readme = "README.md"
8
+ requires-python = ">=3.10"
9
+ dependencies = [
10
+ "pydantic>=2.8.0",
11
+ ]
12
+
13
+ [project.optional-dependencies]
14
+ chutils = ["chutils>=3.5.0"]
15
+ tokens = ["tiktoken>=0.7.0"]
16
+ all = [
17
+ "chutils>=3.5.0",
18
+ "tiktoken>=0.7.0",
19
+ ]
20
+
21
+ [dependency-groups]
22
+ dev = [
23
+ "pytest>=8.0.0",
24
+ "pytest-asyncio>=0.23.0",
25
+ "pytest-mock>=3.12.0",
26
+ "ruff>=0.8.0",
27
+ "mypy>=1.10.0",
28
+ "chutils[rich]>=3.5.0",
29
+ ]
30
+
31
+ [tool.hatch.build.targets.wheel]
32
+ packages = ["src/chllm"]
33
+
34
+ [[tool.uv.index]]
35
+ name = "aliyun"
36
+ url = "https://mirrors.aliyun.com/pypi/simple/"
37
+ default = true
38
+
39
+ [build-system]
40
+ requires = ["hatchling"]
41
+ build-backend = "hatchling.build"
42
+
43
+ [tool.pytest.ini_options]
44
+ pythonpath = ["src"]
45
+ asyncio_mode = "auto"
46
+ testpaths = ["tests"]
47
+ markers = [
48
+ "slow: маркер для долгих тестов",
49
+ ]
50
+
51
+ [tool.ruff]
52
+ target-version = "py310"
53
+ line-length = 120
54
+
55
+ [tool.ruff.lint]
56
+ select = ["E", "F", "W", "I", "UP", "SIM", "RUF"]
57
+ ignore = [
58
+ "RUF001", # Ambiguous unicode characters in strings (русский язык)
59
+ "RUF002", # Ambiguous unicode characters in docstrings
60
+ "RUF003", # Ambiguous unicode characters in comments
61
+ ]
62
+
63
+ [tool.ruff.lint.per-file-ignores]
64
+ "__init__.py" = ["F401"]
65
+ "tests/*" = ["S101"]
66
+
67
+ [tool.mypy]
68
+ python_version = "3.10"
69
+ check_untyped_defs = true
70
+ ignore_missing_imports = true