diff --git a/1_анализ_главы/merge.json b/1_анализ_главы/merge_0.json similarity index 100% rename from 1_анализ_главы/merge.json rename to 1_анализ_главы/merge_0.json diff --git a/1_анализ_главы/merge_jsons_old.py b/1_анализ_главы/merge_jsons.py similarity index 100% rename from 1_анализ_главы/merge_jsons_old.py rename to 1_анализ_главы/merge_jsons.py diff --git a/1_анализ_главы/run_chapter_analysis_ollama.py b/1_анализ_главы/run_chapter_analysis_ollama.py index 71f85cb..d97a96c 100644 --- a/1_анализ_главы/run_chapter_analysis_ollama.py +++ b/1_анализ_главы/run_chapter_analysis_ollama.py @@ -14,13 +14,12 @@ import urllib.request from pathlib import Path OLLAMA_URL = "http://localhost:11434" -MODEL = "qwen3:14b" +MODEL = "qwen3:14b-q8_0" DIR = Path(__file__).resolve().parent OLLAMA_OPTIONS = { "temperature": 0.3, "num_ctx": 9000, - "num_predict": 8500, "repeat_penalty": 1.1, } diff --git a/1_анализ_главы/run_framework_ollama.py b/1_анализ_главы/run_framework_ollama.py index 5c5f8b9..501a19d 100644 --- a/1_анализ_главы/run_framework_ollama.py +++ b/1_анализ_главы/run_framework_ollama.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 """ -Один запуск блока framework через Ollama (qwen3:14b) для сравнения с эталоном выход_frame.json. +Один запуск блока framework через Ollama (qwen3:14b-q8_0) для сравнения с эталоном выход_frame.json. Вход: вход_главы.json, промпт extract_framework_v2.txt. Выход: выход_frame_ollama.json и краткое сравнение с выход_frame.json. """ @@ -13,14 +13,13 @@ import urllib.request from pathlib import Path OLLAMA_URL = "http://localhost:11434" -MODEL = "qwen3:14b" +MODEL = "qwen3:14b-q8_0" DIR = Path(__file__).resolve().parent # Параметры для стабильного структурированного вывода (JSON framework) OLLAMA_OPTIONS = { "temperature": 0.3, # ниже = детерминированнее, меньше «творчества» и смены языка - "num_ctx": 8500, # контекст под длинную главу - "num_predict": 4096, # лимит токенов ответа под полный frame + "num_ctx": 9000, # контекст под длинную главу (совпадает с OLLAMA_NUM_CTX в docker-compose) "repeat_penalty": 1.1, } diff --git a/2_валидация_анализа_по_блокам/run_validation_ollama.py b/2_валидация_анализа_по_блокам/run_validation_ollama.py index 4b18868..d332f85 100644 --- a/2_валидация_анализа_по_блокам/run_validation_ollama.py +++ b/2_валидация_анализа_по_блокам/run_validation_ollama.py @@ -14,15 +14,14 @@ import urllib.request from pathlib import Path OLLAMA_URL = "http://localhost:11434" -MODEL = "qwen3:14b" +MODEL = "qwen3:14b-q8_0" DIR = Path(__file__).resolve().parent DEFAULT_MERGE = DIR.parent / "1_анализ_главы" / "merge.json" DEFAULT_CHAPTER = DIR.parent / "1_анализ_главы" / "вход_главы.json" OLLAMA_OPTIONS = { - "temperature": 0.2, - "num_ctx": 8500, - "num_predict": 2048, + "temperature": 0.3, + "num_ctx": 9000, "repeat_penalty": 1.1, } diff --git a/2_валидация_анализа_по_блокам/validation_status.json b/2_валидация_анализа_по_блокам/validation_status_0.json similarity index 100% rename from 2_валидация_анализа_по_блокам/validation_status.json rename to 2_валидация_анализа_по_блокам/validation_status_0.json diff --git a/2b_финальная_валидация_согласованности/run_consistency_ollama.py b/2b_финальная_валидация_согласованности/run_consistency_ollama.py index 8b525a9..659d1dd 100644 --- a/2b_финальная_валидация_согласованности/run_consistency_ollama.py +++ b/2b_финальная_валидация_согласованности/run_consistency_ollama.py @@ -15,15 +15,14 @@ import urllib.request from pathlib import Path OLLAMA_URL = "http://localhost:11434" -MODEL = "qwen3:14b" +MODEL = "qwen3:14b-q8_0" DIR = Path(__file__).resolve().parent DEFAULT_MERGE = DIR.parent / "1_анализ_главы" / "merge.json" DEFAULT_CHAPTER = DIR.parent / "1_анализ_главы" / "вход_главы.json" OLLAMA_OPTIONS = { - "temperature": 0.2, - "num_ctx": 8500, - "num_predict": 2048, + "temperature": 0.3, + "num_ctx": 9000, "repeat_penalty": 1.1, } diff --git a/3_извлечение_тегов/run_extract_tags_ollama.py b/3_извлечение_тегов/run_extract_tags_ollama.py index 316faae..7a61cb6 100644 --- a/3_извлечение_тегов/run_extract_tags_ollama.py +++ b/3_извлечение_тегов/run_extract_tags_ollama.py @@ -14,7 +14,7 @@ import urllib.request from pathlib import Path OLLAMA_URL = "http://localhost:11434" -MODEL = "qwen3:14b" +MODEL = "qwen3:14b-q8_0" DIR = Path(__file__).resolve().parent DEFAULT_MERGE = DIR.parent / "1_анализ_главы" / "merge.json" DEFAULT_CHAPTER = DIR.parent / "1_анализ_главы" / "вход_главы.json" @@ -22,8 +22,7 @@ DEFAULT_ALLOWED_TAGS = DIR / "allowed_tags.json" OLLAMA_OPTIONS = { "temperature": 0.3, - "num_ctx": 8500, - "num_predict": 2048, + "num_ctx": 9000, "repeat_penalty": 1.1, } diff --git a/4_валидация_тегов/run_validate_tags_ollama.py b/4_валидация_тегов/run_validate_tags_ollama.py index 46c4d0c..17ae66e 100644 --- a/4_валидация_тегов/run_validate_tags_ollama.py +++ b/4_валидация_тегов/run_validate_tags_ollama.py @@ -15,16 +15,15 @@ import urllib.request from pathlib import Path OLLAMA_URL = "http://localhost:11434" -MODEL = "qwen3:14b" +MODEL = "qwen3:14b-q8_0" DIR = Path(__file__).resolve().parent DEFAULT_EXTRACTED_TAGS = DIR.parent / "3_извлечение_тегов" / "extracted_tags.json" DEFAULT_MERGE = DIR.parent / "1_анализ_главы" / "merge.json" DEFAULT_CHAPTER = DIR.parent / "1_анализ_главы" / "вход_главы.json" OLLAMA_OPTIONS = { - "temperature": 0.2, - "num_ctx": 8500, - "num_predict": 2048, + "temperature": 0.3, + "num_ctx": 9000, "repeat_penalty": 1.1, } diff --git a/ARCHITECTURE_SUMMARY.md b/ARCHITECTURE_SUMMARY.md index 3754bfd..1c70c24 100644 --- a/ARCHITECTURE_SUMMARY.md +++ b/ARCHITECTURE_SUMMARY.md @@ -238,7 +238,7 @@ EPUB → JSON с главами → Анализ по блокам (framework ```yaml ollama: environment: - - OLLAMA_NUM_CTX=12000-13000 # Оптимальный компромисс + - OLLAMA_NUM_CTX=9000 # Контекст для анализа глав - OLLAMA_NUM_THREAD=8 # По количеству ядер CPU - OLLAMA_NUM_PARALLEL=1 # Последовательная обработка (экономия памяти) ``` @@ -246,12 +246,12 @@ ollama: #### Ограничения контекста **При 30GB RAM с lazy loading:** -- `qwen3-14b:8bit`: оптимально 12000–13000 токенов (даёт ~10000–11000 для текста главы) +- `qwen3-14b:8bit`: оптимально 9000 токенов (даёт ~7000–8000 для текста главы) - **Эмбеддинги:** bge-m3 — 8192 токенов на вход, размерность 1024. Текст для эмбеддинга — сериализованный анализ главы; при превышении лимита — truncation или стратегия из embed_input_spec.txt (см. этап 6 пайплайна). **Анализ книг:** - Самая большая глава: 11,119 токенов ("Атомные привычки", глава 5) -- Все главы влезают в контекст 12000-13000 токенов +- Все главы влезают в контекст 9000 токенов - С оптимизированными промптами (~200-300 токенов) остается достаточно места **Для 20000 токенов контекста:** @@ -1254,7 +1254,7 @@ ollama ps 1. **Lazy loading моделей** - загружать по требованию, выгружать через `keep_alive: 0` 2. **Оптимизировать промпты** - минимум токенов (~200-300 вместо 1000-2000) -3. **OLLAMA_NUM_CTX=12000-13000** - компромисс между памятью и возможностями +3. **OLLAMA_NUM_CTX=9000** - компромисс между памятью и возможностями 4. **Обработка строго последовательно** - одна глава, одна модель за раз 5. **Мониторить память** - следить за использованием RAM diff --git a/docker-compose.yml b/docker-compose.yml index ea1d9b6..7cc1030 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -58,8 +58,8 @@ services: - app-network environment: - OLLAMA_HOST=0.0.0.0:11434 - # Контекст для qwen3:14b (анализ глав). Рекомендация ARCHITECTURE: 12000–13000. - - OLLAMA_NUM_CTX=12000 + # Контекст для qwen3:14b-q8_0 (анализ глав). + - OLLAMA_NUM_CTX=9000 healthcheck: test: ["CMD", "curl", "-f", "http://localhost:11434/api/tags"] interval: 30s diff --git a/docs/check_ollama_model.py b/docs/check_ollama_model.py new file mode 100644 index 0000000..da5a3e2 --- /dev/null +++ b/docs/check_ollama_model.py @@ -0,0 +1,63 @@ +#!/usr/bin/env python3 +""" +Проверка деталей модели в Ollama: квантизация, размер, контекст. +Использование: + python docs/check_ollama_model.py + OLLAMA_URL=http://192.168.88.15:11434 python docs/check_ollama_model.py + OLLAMA_URL=... MODEL=qwen3:14b python docs/check_ollama_model.py +""" + +import json +import os +import urllib.request + +OLLAMA_URL = os.environ.get("OLLAMA_URL", "http://localhost:11434") +MODEL = os.environ.get("MODEL", "qwen3:14b-q8_0") + + +def main() -> None: + url = f"{OLLAMA_URL.rstrip('/')}/api/show" + body = json.dumps({"model": MODEL}).encode("utf-8") + req = urllib.request.Request(url, data=body, method="POST") + req.add_header("Content-Type", "application/json") + try: + with urllib.request.urlopen(req, timeout=10) as resp: + data = json.load(resp) + except urllib.error.URLError as e: + print(f"Ошибка подключения к {OLLAMA_URL}: {e}") + raise SystemExit(1) + except urllib.error.HTTPError as e: + print(f"HTTP {e.code}: {e.reason}") + if e.fp: + try: + body = e.fp.read().decode("utf-8", errors="replace") + print(body[:500]) + except Exception: + pass + raise SystemExit(1) + + details = data.get("details") or {} + info = data.get("model_info") or {} + + print(f"Модель: {MODEL}") + print(f"Ollama: {OLLAMA_URL}") + print("-" * 40) + print(f"Формат: {details.get('format', '—')}") + print(f"Квантизация: {details.get('quantization_level', '—')}") + print(f"Размер (params): {details.get('parameter_size', '—')}") + print(f"Семейство: {details.get('family', '—')}") + + # Контекст из model_info (ключ зависит от семейства: qwen3.context_length и т.д.) + for key, val in info.items(): + if "context_length" in key: + print(f"Контекст (токенов): {val}") + break + else: + print("Контекст (токенов): —") + + if data.get("modified_at"): + print(f"Изменён: {data['modified_at']}") + + +if __name__ == "__main__": + main() diff --git a/docs/cpu-time-estimate.md b/docs/cpu-time-estimate.md index b81e595..e201254 100644 --- a/docs/cpu-time-estimate.md +++ b/docs/cpu-time-estimate.md @@ -1,4 +1,4 @@ -# Оценка времени пайплайна на CPU (Ollama, qwen3:14b) +# Оценка времени пайплайна на CPU (Ollama, qwen3:14b-q8_0) Оценка основана на архитектуре (этапы 1–4 — вызовы LLM) и замере: **один блок framework на CPU ≈ 15+ минут** (до ответа или до 500). diff --git a/docs/ollama-models.md b/docs/ollama-models.md index 8756efc..1e1522c 100644 --- a/docs/ollama-models.md +++ b/docs/ollama-models.md @@ -4,7 +4,7 @@ | Назначение | Модель в Ollama | Команда pull | Примечание | |------------|-----------------|--------------|------------| -| LLM: анализ и валидация (шаги 1–4) | `qwen3:14b` | `ollama pull qwen3:14b` | ~9.3 GB (Q4_K_M). Ближе к 8bit: `qwen3:14b-q8_0` (~16 GB). | +| LLM: анализ и валидация (шаги 1–4) | `qwen3:14b-q8_0` | `ollama pull qwen3:14b-q8_0` | ~16 GB (Q8). Легче: `qwen3:14b` (~9.3 GB, Q4_K_M). | | Эмбеддинги (шаг 6) | `bge-m3` | `ollama pull bge-m3` | ~1.2 GB, размерность 1024, контекст 8192. | ## Загрузка моделей при работе через Docker @@ -19,7 +19,7 @@ ```bash # LLM для анализа глав и валидации - docker exec -it ollama ollama pull qwen3:14b + docker exec -it ollama ollama pull qwen3:14b-q8_0 # Модель эмбеддингов docker exec -it ollama ollama pull bge-m3 @@ -39,10 +39,10 @@ ## Варианты LLM -- **qwen3:14b** — по умолчанию, меньше по размеру (~9.3 GB). -- **qwen3:14b-q8_0** — выше качество, ближе к «8bit» из архитектуры (~16 GB). +- **qwen3:14b-q8_0** — по умолчанию, выше качество, меньше галлюцинаций (~16 GB). +- **qwen3:14b** — легче по размеру (~9.3 GB, Q4_K_M). -В коде пайплайна имя модели задаётся конфигом (например, `OLLAMA_LLM_MODEL=qwen3:14b`). +В коде пайплайна имя модели задаётся конфигом (например, `OLLAMA_LLM_MODEL=qwen3:14b-q8_0`). ## Параметры генерации (options) для LLM @@ -51,8 +51,7 @@ | Параметр | Значение | Назначение | |----------------|----------|------------| | `temperature` | 0.3 | Ниже = детерминированнее ответ, меньше смены языка и «творчества». Для извлечения frame лучше 0.2–0.5. | -| `num_ctx` | 8192 | Размер контекста (токены). Должен вмещать главу + промпт. | -| `num_predict` | 4096 | Макс. токенов ответа, чтобы полный JSON не обрезался. | +| `num_ctx` | 9000 | Размер контекста (токены). Совпадает с OLLAMA_NUM_CTX в docker-compose. | | `repeat_penalty` | 1.1 | Снижает повторения в тексте. | Изменить можно в коде (`OLLAMA_OPTIONS`) или через переменные окружения, если скрипт будет их читать. @@ -62,7 +61,7 @@ Если Ollama установлен локально: ```bash -ollama pull qwen3:14b +ollama pull qwen3:14b-q8_0 ollama pull bge-m3 ollama list ```