AnatoliiG commited on
Commit
047143f
·
1 Parent(s): 1080c74

fix repeat haluc

Browse files
Files changed (2) hide show
  1. src/core/engine.py +1 -0
  2. src/ui/callbacks.py +32 -13
src/core/engine.py CHANGED
@@ -49,6 +49,7 @@ class ModelEngine:
49
  "max_tokens": int(kwargs.get("max_tokens", settings.DEFAULT_MAX_TOKENS)),
50
  "temperature": float(kwargs.get("temperature", settings.DEFAULT_TEMP)),
51
  "top_p": float(kwargs.get("top_p", 0.95)),
 
52
  "stop": kwargs.get("stop", []),
53
  "stream": stream_mode,
54
  }
 
49
  "max_tokens": int(kwargs.get("max_tokens", settings.DEFAULT_MAX_TOKENS)),
50
  "temperature": float(kwargs.get("temperature", settings.DEFAULT_TEMP)),
51
  "top_p": float(kwargs.get("top_p", 0.95)),
52
+ "repeat_penalty": float(kwargs.get("repeat_penalty", 1.15)),
53
  "stop": kwargs.get("stop", []),
54
  "stream": stream_mode,
55
  }
src/ui/callbacks.py CHANGED
@@ -35,16 +35,33 @@ def set_interactive(is_interactive):
35
  def bot_response(
36
  history, system_prompt, temperature, max_tokens, use_search, uploaded_file
37
  ):
38
- # ПРЕДОХРАНИТЕЛЬ: Запрещаем основной модели выводить технические команды текстом.
39
- system_guard = (
40
- "\n\n[ВАЖНО]: Отвечай пользователю напрямую обычным текстом. "
41
- "КАТЕГОРИЧЕСКИ ЗАПРЕЩАЕТСЯ выводить технические команды, массивы или JSON-вызовы (например [{'type': 'search'}]). "
42
- "Если тебе нужно рассуждать перед ответом, оборачивай свои мысли СТРОГО в теги <think>твои мысли</think>."
43
- )
44
- messages = [{"role": "system", "content": system_prompt + system_guard}]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
  file_info, file_content = "", ""
46
 
47
- # --- 1. ОБРАБОТКА ФАЙЛА ---
48
  if uploaded_file and os.path.exists(uploaded_file):
49
  filename = os.path.basename(uploaded_file)
50
  size_kb = os.path.getsize(uploaded_file) / 1024
@@ -56,7 +73,7 @@ def bot_response(
56
  if "[Ошибка" in file_content:
57
  file_info = f"❌ **Ошибка файла:** `{filename}`"
58
 
59
- # --- 2. ОЧИСТКА И ФОРМИРОВАНИЕ ИСТОРИИ ---
60
  for msg in history[-7:]:
61
  content = str(msg["content"])
62
  if msg["role"] == "assistant":
@@ -68,7 +85,7 @@ def bot_response(
68
  content = re.sub(r"<details.*?>.*?</details>", "", content, flags=re.DOTALL)
69
  content = re.sub(r"<think>.*?</think>", "", content, flags=re.DOTALL)
70
 
71
- # ИСПРАВЛЕНИЕ: Вырезаем технические массивы поиска, если они проскочили в прошлых ответах
72
  content = re.sub(
73
  r"\[\s*\{.*?['\"]type['\"]\s*:\s*['\"]search['\"].*?\}\s*\]",
74
  "",
@@ -85,7 +102,7 @@ def bot_response(
85
  history.append({"role": "assistant", "content": "⏳ Инициализация..."})
86
  yield history
87
 
88
- # --- 3. АГЕНТ ПОИСКА (РОУТЕР) ---
89
  search_info = ""
90
  if use_search:
91
  history[-1]["content"] = (
@@ -114,7 +131,7 @@ def bot_response(
114
  eval_response = engine.generate(
115
  messages=agent_messages,
116
  max_tokens=150,
117
- temperature=0.0, # Обязательно 0! Нам нужна точность, а не креатив.
118
  stream=False,
119
  )
120
 
@@ -150,6 +167,7 @@ def bot_response(
150
  print(f"Ошибка Роутера: {e}")
151
  search_info = "⚡ Ошибка роутера. Отвечаю из базы знаний."
152
 
 
153
  if file_content:
154
  messages[0]["content"] += (
155
  f"\n\nСодержимое файла '{os.path.basename(uploaded_file)}':\n\n{file_content}"
@@ -164,12 +182,13 @@ def bot_response(
164
  history[-1]["content"] = status_header + "⏳ Генерация ответа..."
165
  yield history
166
 
167
- # --- 4. СТРИМИНГ И УМНЫЙ UI ---
168
  try:
169
  stream = engine.generate(
170
  messages=messages,
171
  max_tokens=max_tokens,
172
  temperature=temperature,
 
173
  stream=True,
174
  )
175
  partial_text = ""
 
35
  def bot_response(
36
  history, system_prompt, temperature, max_tokens, use_search, uploaded_file
37
  ):
38
+ # --- 1. ДИНАМИЧЕСКИЙ ПРОМПТ И ПРЕДОХРАНИТЕЛЬ ---
39
+ actual_sys_prompt = system_prompt
40
+
41
+ if use_search:
42
+ system_guard = (
43
+ "\n\n[ВАЖНО]: Отвечай пользователю напрямую обычным текстом. "
44
+ "КАТЕГОРИЧЕСКИ ЗАПРЕЩАЕТСЯ выводить технические команды, массивы или JSON-вызовы (например [{'type': 'search'}]). "
45
+ "Если тебе нужно рассуждать перед ответом, оборачивай свои мысли СТРОГО в теги <think>твои мысли</think>."
46
+ )
47
+ else:
48
+ # Если галочка поиска выключена, удаляем из системного промпта призыв искать
49
+ actual_sys_prompt = actual_sys_prompt.replace(
50
+ "Если нужно узнать свежую информацию, используйте поиск.", ""
51
+ )
52
+
53
+ system_guard = (
54
+ "\n\n[СИСТЕМНОЕ УВЕДОМЛЕНИЕ]: ВНИМАНИЕ! Функция поиска в интернете сейчас ОТКЛЮЧЕНА. "
55
+ "Ты ДОЛЖЕН ответить, используя только свои внутренние знания. "
56
+ "НИ В КОЕМ СЛУЧАЕ не пытайся генерировать команды поиска (например [{'type': 'search'}]). "
57
+ "Просто дай лучший ответ, который можешь, основываясь на своей памяти. "
58
+ "Если тебе нужно рассуждать, используй теги <think>мысли</think>."
59
+ )
60
+
61
+ messages = [{"role": "system", "content": actual_sys_prompt + system_guard}]
62
  file_info, file_content = "", ""
63
 
64
+ # --- 2. ОБРАБОТКА ФАЙЛА ---
65
  if uploaded_file and os.path.exists(uploaded_file):
66
  filename = os.path.basename(uploaded_file)
67
  size_kb = os.path.getsize(uploaded_file) / 1024
 
73
  if "[Ошибка" in file_content:
74
  file_info = f"❌ **Ошибка файла:** `{filename}`"
75
 
76
+ # --- 3. ОЧИСТКА И ФОРМИРОВАНИЕ ИСТОРИИ ---
77
  for msg in history[-7:]:
78
  content = str(msg["content"])
79
  if msg["role"] == "assistant":
 
85
  content = re.sub(r"<details.*?>.*?</details>", "", content, flags=re.DOTALL)
86
  content = re.sub(r"<think>.*?</think>", "", content, flags=re.DOTALL)
87
 
88
+ # Вырезаем технические массивы поиска, если они проскочили в прошлых ответах
89
  content = re.sub(
90
  r"\[\s*\{.*?['\"]type['\"]\s*:\s*['\"]search['\"].*?\}\s*\]",
91
  "",
 
102
  history.append({"role": "assistant", "content": "⏳ Инициализация..."})
103
  yield history
104
 
105
+ # --- 4. АГЕНТ ПОИСКА (РОУТЕР) ---
106
  search_info = ""
107
  if use_search:
108
  history[-1]["content"] = (
 
131
  eval_response = engine.generate(
132
  messages=agent_messages,
133
  max_tokens=150,
134
+ temperature=0.0, # Обязательно 0 для точности!
135
  stream=False,
136
  )
137
 
 
167
  print(f"Ошибка Роутера: {e}")
168
  search_info = "⚡ Ошибка роутера. Отвечаю из базы знаний."
169
 
170
+ # Добавляем контент файла в начало (чтобы модель опиралась на него при ответе)
171
  if file_content:
172
  messages[0]["content"] += (
173
  f"\n\nСодержимое файла '{os.path.basename(uploaded_file)}':\n\n{file_content}"
 
182
  history[-1]["content"] = status_header + "⏳ Генерация ответа..."
183
  yield history
184
 
185
+ # --- 5. СТРИМИНГ И УМНЫЙ UI ---
186
  try:
187
  stream = engine.generate(
188
  messages=messages,
189
  max_tokens=max_tokens,
190
  temperature=temperature,
191
+ repeat_penalty=1.15, # Штраф за зацикливание текста
192
  stream=True,
193
  )
194
  partial_text = ""