File size: 3,920 Bytes
c6c602e
9700948
c6c602e
9700948
c6c602e
9700948
 
 
f34d9e8
9700948
f34d9e8
 
 
 
 
 
 
c6c602e
 
 
 
 
 
f34d9e8
9700948
 
 
 
 
 
 
 
 
 
 
c6c602e
9700948
c6c602e
9700948
 
c6c602e
9700948
 
 
 
 
c6c602e
 
9700948
 
c6c602e
 
 
9700948
c6c602e
 
 
 
 
 
 
 
 
 
9700948
c6c602e
 
9700948
 
1080c74
c23e8fc
1080c74
 
 
c23e8fc
 
7e12323
c23e8fc
 
 
 
1080c74
c23e8fc
 
 
 
 
 
 
 
 
 
7e12323
1080c74
c23e8fc
 
1080c74
c23e8fc
 
 
 
 
1080c74
c23e8fc
 
 
 
 
 
 
 
 
1080c74
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
import json
import os
import re

import pypdf
from duckduckgo_search import DDGS


def get_clean_text(content):
    """Извлекает чистый текст из любого формата (str, dict, list)."""
    if content is None:
        return ""
    if isinstance(content, str):
        return content
    if isinstance(content, dict):
        return content.get("text", "")
    if isinstance(content, list):
        return "".join(
            [
                item if isinstance(item, str) else item.get("text", "")
                for item in content
            ]
        )
    return str(content)


def extract_text_from_file(file_path):
    """Читает текст из загруженного файла."""
    if not file_path or not os.path.exists(file_path):
        return ""
    ext = os.path.splitext(file_path)[1].lower()
    try:
        if ext == ".pdf":
            text = ""
            with open(file_path, "rb") as f:
                reader = pypdf.PdfReader(f)
                for page in reader.pages:
                    text += (page.extract_text() or "") + "\n"
            return text
        else:
            with open(file_path, "r", encoding="utf-8", errors="ignore") as f:
                return f.read()
    except Exception as e:
        return f"[Ошибка чтения файла: {e}]"


def web_search(query: str, max_results: int = 3) -> list:
    """Выполняет поиск в интернете через DuckDuckGo и возвращает список словарей."""
    try:
        with DDGS() as ddgs:
            results = list(ddgs.text(query, max_results=max_results))
            if not results:
                return []

            formatted_results = []
            for r in results:
                formatted_results.append(
                    {
                        "title": r.get("title", ""),
                        "url": r.get("href", ""),
                        "snippet": r.get("body", ""),
                    }
                )
            return formatted_results
    except Exception as e:
        print(f"Ошибка DDGS: {e}")
        return []


def extract_search_query(text: str):
    """Супер-надежный парсер запроса (с поддержкой XML, JSON и логов)."""
    if not text:
        return None

    # ВЫВОДИМ В КОНСОЛЬ ТО, ЧТО РЕАЛЬНО ПОДУМАЛ РОУТЕР
    print(f"\n--- [DEBUG] RAW ROUTER OUTPUT ---\n{text}\n---------------------------\n")

    # 1. Очищаем от размышлений
    clean = re.sub(r"<think>.*?</think>", "", text, flags=re.DOTALL).strip()
    if not clean:
        clean = text

    # 2. Ищем XML-тег (наш новый основной метод)
    xml_match = re.search(r"<search>(.*?)</search>", clean, re.IGNORECASE)
    if xml_match:
        return xml_match.group(1).strip()

    # 3. Резерв на случай JSON
    json_match = re.search(r"\{.*?\}", clean, re.DOTALL)
    if json_match:
        try:
            data = json.loads(json_match.group(0))
            if data.get("search") is True or str(data.get("search")).lower() == "true":
                return data.get("query")
        except:
            pass

    # 4. Резерв на случай "старых галлюцинаций" с массивами
    if "search" in text.lower():
        match = re.search(
            r"(?:запрос|query|text)['\"]\s*:\s*['\"]([^'\"]+)['\"]", text, re.IGNORECASE
        )
        if match:
            val = match.group(1)
            val = re.sub(
                r"^(?:🔍\s*)?(?:Поиск(?:\s*по\s*запросу)?|Search):\s*",
                "",
                val,
                flags=re.IGNORECASE,
            ).strip()
            if val and val.lower() not in ["no", "false", "none", "no_search"]:
                return val

    return None