""" extractor.py — Извлечение строк спецификации из текста документа. Берёт распарсенный текст (parsed_text из documents), отправляет LLM, получает структурированный список строк спецификации. Не зависит от parser.py, textify.py, upload.py. Зависит только от llm_client.py. """ import json import llm_client def extract(parsed_text: str) -> dict: """ Извлечь строки спецификации из текста документа через LLM. Args: parsed_text: текст документа (выдача textify.py) Returns: {"rows": [{row_num, name, price, qty, sum, date_start}, ...], "unresolved": [...]} или {"error": "...", "raw_response": "..."} """ # ── Промпт ────────────────────────────────────────────────── prompt = f"""Ты — анализатор договоров. Ниже текст спецификации услуг из договора облачного провайдера. Найди ВСЕ таблицы со списком услуг. Извлеки каждую строку в JSON-массив. Для каждой строки верни: - row_num: номер по порядку (целое число) - name: полное наименование услуги (весь текст из ячейки) - price: цена за единицу в рублях (число, из колонки "Цена") - qty: количество/объём (число, из колонки "Объем") - sum: итоговая сумма (число, из колонки "Сумма") - date_start: дата начала оказания (строка YYYY-MM-DD) ПРАВИЛА: 1. Пропускай итоговые строки ("Итого...") и строки с подписями. 2. Если ячейка пустая — ставь null. 3. Если не можешь определить значение — ставь null и добавь в unresolved. 4. Верни ТОЛЬКО JSON, без пояснений. Пример ответа: {{"rows":[{{"row_num":1,"name":"Аренда стойко-места","price":213905.44,"qty":3,"sum":641716.32,"date_start":"2026-04-01"}}],"unresolved":[]}} Текст документа: --- {parsed_text} --- """ # ── Вызов LLM ──────────────────────────────────────────────── result = llm_client.ask(prompt, max_tokens=8000) if "error" in result: return {"error": result["error"]} # ── Парсинг ответа ─────────────────────────────────────────── raw_text = result.get("text", "") try: # Найти JSON в ответе (может быть обёрнут в ```json ... ```) json_text = raw_text if "```json" in json_text: json_text = json_text.split("```json")[1].split("```")[0] elif "```" in json_text: json_text = json_text.split("```")[1].split("```")[0] data = json.loads(json_text.strip()) rows = data.get("rows", []) unresolved = data.get("unresolved", []) return { "rows": rows, "unresolved": unresolved, "model": result.get("model", ""), "usage": result.get("usage", {}), } except (json.JSONDecodeError, IndexError, KeyError) as e: return { "error": f"parse_failed: {e}", "raw_response": raw_text[:1000], }