File size: 4,969 Bytes
ca0b91b
1715337
1010f3d
4d9be7b
1715337
c24cf02
4d9be7b
1715337
 
31c2124
 
 
 
 
 
4d9be7b
 
 
 
31c2124
608ce41
4d9be7b
 
 
 
 
 
 
 
ddc557f
d7e3cb2
4d9be7b
24c09a6
4d9be7b
 
 
 
 
 
 
 
24c09a6
4d9be7b
d7e3cb2
 
 
4d9be7b
c24cf02
4d9be7b
31c2124
c24cf02
 
 
4d9be7b
c24cf02
d7e3cb2
 
c24cf02
 
 
d7e3cb2
c24cf02
4d9be7b
d7e3cb2
4d9be7b
d7e3cb2
 
 
4d9be7b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
109cadc
 
4d9be7b
 
ca0b91b
c24cf02
31c2124
4d9be7b
 
ca0b91b
49d825e
109cadc
 
 
8baa2b5
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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# app.py
import json
import random
import re
from difflib import get_close_matches
from huggingface_hub import InferenceClient
from ddgs import DDGS
import gradio as gr

# === Загрузка patterns.json ===
try:
    with open("patterns.json", "r", encoding="utf-8") as f:
        PATTERNS = json.load(f)
except:
    PATTERNS = {
        "привет": ["Привет!"],
        "пока": ["До свидания!"],
        "default": ["Не знаю."],
        "knowledge": {}
    }

KEYWORDS = {
    "привет": ["привет", "здравствуй", "хай", "прив", "здарова"],
    "как дела": ["дела", "как ты", "ты как", "настроение"],
    "имя": ["имя", "кто ты", "зовут", "тебя зовут"],
    "школа": ["школа", "урок", "задача", "домашка", "математика", "геометрия"],
    "пока": ["пока", "выход", "quit", "до свидания", "закончить", "стоп"],
    "knowledge": ["что такое", "как приготовить", "что значит", "расскажи про", "как сделать"]
}

def preprocess(text):
    return re.sub(r'[^а-яё\s]', ' ', text.lower()).strip()

# === Веб-поиск ===
def web_search(query, max_results=3):
    try:
        with DDGS() as ddgs:
            results = ddgs.text(query, region="ru-ru", max_results=max_results)
            return "\n".join([f"{r['title']}: {r['body']}" for r in results])
    except Exception as e:
        return f"Поиск недоступен."

# === Inference API (публичная модель, без токена) ===
MODEL_ID = "TinyLlama/TinyLlama-1.1B-Chat-v1.0"
client = InferenceClient()

def neural_generate(prompt_text):
    try:
        messages = [{"role": "user", "content": prompt_text}]
        response = ""
        for chunk in client.chat_completion(
            messages,
            model=MODEL_ID,
            max_tokens=256,
            temperature=0.6,
            top_p=0.92,
            stream=True
        ):
            token = chunk.choices[0].delta.content or ""
            response += token
        return response.strip()
    except Exception as e:
        return f"Ошибка генерации: {str(e)[:100]}"

# === Основная логика (гибрид Micro + MAX) ===
def respond(message, history):
    user_input = message.strip()
    if not user_input:
        return "Введите запрос."

    user_lower = user_input.lower()

    # Система (заглушка)
    if user_lower.startswith("система:"):
        return "🔒 Управление ОС недоступно в демо."

    # Веб-поиск
    if user_lower.startswith("поиск:"):
        query = user_input[6:].strip()
        if not query:
            return "🔍 Пример: `поиск: погода в Москве`"
        yield "🔍 Ищу...\n"
        context = web_search(query)
        prompt = (
            f"ИНФОРМАЦИЯ ИЗ ИНТЕРНЕТА:\n{context}\n\n"
            f"Кратко ответь на русском: {query}"
        )
        yield neural_generate(prompt)
        return

    # === Newton Micro логика ===
    clean = preprocess(user_input)
    if clean:
        if any(w in clean for w in ["пока", "выход", "стоп", "quit", "закончить"]):
            yield random.choice(PATTERNS["пока"])
            return

        knowledge = PATTERNS.get("knowledge", {})
        if clean in knowledge:
            yield knowledge[clean]
            return
        matches = get_close_matches(clean, knowledge.keys(), n=1, cutoff=0.6)
        if matches:
            yield knowledge[matches[0]]
            return

        all_keywords = []
        keyword_to_intent = {}
        for intent, words in KEYWORDS.items():
            if intent == "knowledge":
                continue
            for w in words:
                all_keywords.append(w)
                keyword_to_intent[w] = intent
        for token in clean.split():
            kw_match = get_close_matches(token, all_keywords, n=1, cutoff=0.6)
            if kw_match:
                intent = keyword_to_intent[kw_match[0]]
                yield random.choice(PATTERNS[intent])
                return

    # Fallback на нейросеть
    prompt = f"Ответь кратко на русском: {user_input}"
    yield neural_generate(prompt)

# === Gradio интерфейс ===
chatbot = gr.ChatInterface(
    respond,
    title="Newton MAX (Micro + MAX)",
    description="Поддержка: `поиск: ...`, `система: ...`",
    examples=[
        ["Привет!", None],
        ["Что такое ИИ?", None],
        ["поиск: что такое UncomOS", None],
        ["система: выключи компьютер", None]
    ],
    theme="soft"
)

if __name__ == "__main__":
    chatbot.launch()