Kolyadual commited on
Commit
1715337
·
verified ·
1 Parent(s): 2bb4c6a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +113 -45
app.py CHANGED
@@ -1,12 +1,46 @@
1
  # app.py
2
- import gradio as gr
3
- from huggingface_hub import InferenceClient
 
 
 
 
4
  from ddgs import DDGS
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
 
6
- # Публичная модель → токен НЕ нужен!
7
- MODEL_NAME = "openai/gpt-oss-20b"
8
- client = InferenceClient() # ← без токена!
9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  def web_search(query, max_results=3):
11
  try:
12
  with DDGS() as ddgs:
@@ -15,64 +49,98 @@ def web_search(query, max_results=3):
15
  except Exception as e:
16
  return f"Ошибка поиска: {str(e)[:100]}"
17
 
18
- def respond(message, history, system_message, max_tokens, temperature, top_p):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  user_input = message.strip()
20
  user_lower = user_input.lower()
21
 
 
22
  if user_lower.startswith("система:"):
23
- return "🔒 Управление системой недоступно в демо-версии."
 
 
 
 
 
 
 
 
24
 
 
25
  if user_lower.startswith("поиск:"):
26
  query = user_input[6:].strip()
27
  if not query:
28
  return "🔍 Пример: `поиск: погода в Москве`"
29
- yield "🔍 Ищу...\n"
30
  context = web_search(query)
31
- full_prompt = (
32
- f"{system_message}\n\n"
33
- f"ИНФОРМАЦИЯ ИЗ ИНТЕРНЕТА:\n{context}\n\n"
34
- f"ВОПРОС: {query}\nОТВЕТ НА РУССКОМ:"
35
  )
36
- else:
37
- full_prompt = f"{system_message}\n\nВОПРОС: {user_input}\nОТВЕТ НА РУССКОМ:"
38
 
39
- messages = [{"role": "user", "content": full_prompt}]
 
 
 
40
 
41
- response = ""
42
- try:
43
- for chunk in client.chat_completion(
44
- messages,
45
- model=MODEL_NAME,
46
- max_tokens=max_tokens,
47
- stream=True,
48
- temperature=temperature,
49
- top_p=top_p,
50
- ):
51
- token = chunk.choices[0].delta.content or ""
52
- response += token
53
- yield response
54
- except Exception as e:
55
- yield f"⚠️ Ошибка: {str(e)}"
56
 
 
57
  chatbot = gr.ChatInterface(
58
  respond,
59
- type="messages",
60
- additional_inputs=[
61
- gr.Textbox(
62
- value="Ты — Newton MAX. Отвечай кратко, точно и только на русском языке.",
63
- label="Системное сообщение"
64
- ),
65
- gr.Slider(1, 1024, 512, label="Макс. токенов"),
66
- gr.Slider(0.1, 1.5, 0.7, label="Температура"),
67
- gr.Slider(0.1, 1.0, 0.92, label="Top-p"),
68
- ],
69
- title="🚀 Newton MAX (gpt-oss-20b + поиск)",
70
- description="Работает без входа! Поддержка: `поиск: ...`",
71
  examples=[
72
- ["Привет!", "Ты — Newton MAX...", 512, 0.7, 0.92],
73
- ["Что такое ИИ?", "Ты — Newton MAX...", 512, 0.7, 0.92],
74
- ["поиск: последние новости", "Ты — Newton MAX...", 768, 0.8, 0.95],
 
75
  ],
 
76
  )
77
 
78
  if __name__ == "__main__":
 
1
  # app.py
2
+ import os
3
+ import json
4
+ import re
5
+ import torch
6
+ from difflib import get_close_matches
7
+ from transformers import AutoTokenizer, AutoModelForCausalLM
8
  from ddgs import DDGS
9
+ import gradio as gr
10
+
11
+ # === Загрузка patterns.json ===
12
+ PATTERNS = {}
13
+ HAS_PATTERNS = False
14
+ try:
15
+ with open("patterns.json", "r", encoding="utf-8") as f:
16
+ PATTERNS = json.load(f)
17
+ HAS_PATTERNS = True
18
+ except:
19
+ pass
20
+
21
+ KEYWORDS = {
22
+ "привет": ["привет", "здравствуй", "хай"],
23
+ "как дела": ["дела", "как ты", "настроение"],
24
+ "имя": ["имя", "кто ты", "зовут"],
25
+ "пока": ["пока", "выход", "до свидания", "стоп"]
26
+ }
27
 
28
+ def preprocess(text):
29
+ return re.sub(r'[^а-яё\s]', ' ', text.lower()).strip()
 
30
 
31
+ # === Загрузка TinyLlama (без токена!) ===
32
+ print("Загрузка TinyLlama с Hugging Face Hub...")
33
+ MODEL_ID = "TinyLlama/TinyLlama-1.1B-Chat-v1.0"
34
+ tokenizer = AutoTokenizer.from_pretrained(MODEL_ID, trust_remote_code=False)
35
+ model = AutoModelForCausalLM.from_pretrained(
36
+ MODEL_ID,
37
+ torch_dtype=torch.float16 if torch.cuda.is_available() else torch.float32,
38
+ device_map="auto",
39
+ low_cpu_mem_usage=True
40
+ )
41
+ print("✅ TinyLlama готова!")
42
+
43
+ # === Веб-поиск ===
44
  def web_search(query, max_results=3):
45
  try:
46
  with DDGS() as ddgs:
 
49
  except Exception as e:
50
  return f"Ошибка поиска: {str(e)[:100]}"
51
 
52
+ # === Генерация через TinyLlama ===
53
+ def generate_with_tinyllama(prompt_text, max_tokens=256):
54
+ try:
55
+ inputs = tokenizer(prompt_text, return_tensors="pt").to(model.device)
56
+ outputs = model.generate(
57
+ **inputs,
58
+ max_new_tokens=max_tokens,
59
+ do_sample=True,
60
+ temperature=0.6,
61
+ top_p=0.92,
62
+ pad_token_id=tokenizer.eos_token_id,
63
+ repetition_penalty=1.1
64
+ )
65
+ full = tokenizer.decode(outputs[0], skip_special_tokens=True)
66
+ if "<|assistant|>" in full:
67
+ return full.split("<|assistant|>")[-1].strip()
68
+ else:
69
+ return full[len(prompt_text):].strip()
70
+ except Exception as e:
71
+ return f"Ошибка генерации: {str(e)[:100]}"
72
+
73
+ # === Fallback через patterns.json ===
74
+ def get_fallback_response(user_input):
75
+ if not HAS_PATTERNS:
76
+ return None
77
+ clean = preprocess(user_input)
78
+ if not clean:
79
+ return None
80
+ if any(w in clean for w in ["пока", "выход", "стоп", "до свидания"]):
81
+ return random.choice(PATTERNS["пока"])
82
+ knowledge = PATTERNS.get("knowledge", {})
83
+ if clean in knowledge:
84
+ return knowledge[clean]
85
+ matches = get_close_matches(clean, knowledge.keys(), n=1, cutoff=0.6)
86
+ if matches:
87
+ return knowledge[matches[0]]
88
+ for intent, words in KEYWORDS.items():
89
+ if any(get_close_matches(token, words, n=1, cutoff=0.6) for token in clean.split()):
90
+ return random.choice(PATTERNS[intent])
91
+ return None
92
+
93
+ # === Основная логика ===
94
+ def respond(message, history):
95
  user_input = message.strip()
96
  user_lower = user_input.lower()
97
 
98
+ # === Системные команды (заглушка) ===
99
  if user_lower.startswith("система:"):
100
+ return "🔒 Управление ОС недоступно в демо."
101
+
102
+ # === Перевод ===
103
+ if user_lower.startswith("перевод:"):
104
+ text = user_input[8:].strip()
105
+ if not text:
106
+ return "🔤 Пример: `перевод: Hello, how are you?`"
107
+ prompt = f"<|user|>\nПереведи на русский язык: {text}\n<|assistant|>\n"
108
+ return generate_with_tinyllama(prompt, max_tokens=128)
109
 
110
+ # === Веб-поиск ===
111
  if user_lower.startswith("поиск:"):
112
  query = user_input[6:].strip()
113
  if not query:
114
  return "🔍 Пример: `поиск: погода в Москве`"
 
115
  context = web_search(query)
116
+ prompt = (
117
+ f"<|user|>\nИнформация из интернета:\n{context}\n\n"
118
+ f"Кратко ответь на русском: {query}\n"
119
+ f"<|assistant|>\n"
120
  )
121
+ return generate_with_tinyllama(prompt, max_tokens=256)
 
122
 
123
+ # === Fallback через patterns.json ===
124
+ fallback = get_fallback_response(user_input)
125
+ if fallback:
126
+ return fallback
127
 
128
+ # === Обычный режим ===
129
+ prompt = f"<|user|>\n{user_input}\nОтветь кратко на русском.\n<|assistant|>\n"
130
+ return generate_with_tinyllama(prompt, max_tokens=256)
 
 
 
 
 
 
 
 
 
 
 
 
131
 
132
+ # === Gradio интерфейс ===
133
  chatbot = gr.ChatInterface(
134
  respond,
135
+ title="🚀 Newton MAX (TinyLlama + поиск + перевод)",
136
+ description="Поддержка команд: `поиск: ...`, `перевод: ...`, `система: ...`",
 
 
 
 
 
 
 
 
 
 
137
  examples=[
138
+ "Привет!",
139
+ "Что такое квантовый компьютер?",
140
+ "поиск: курс доллара",
141
+ "перевод: How are you doing today?"
142
  ],
143
+ theme="soft"
144
  )
145
 
146
  if __name__ == "__main__":