Update 3 files

- /rag/rag_orchestrator.py
- /tests/test_hierarchical_summarize.py
- /template_bot_profile/bot.conf.sample
This commit is contained in:
Markov Andrey
2026-06-30 12:51:14 +00:00
parent abaceea653
commit 405dea3fa3
3 changed files with 148 additions and 24 deletions

View File

@@ -33,6 +33,7 @@ from core.functions.check_consistency import check_consistency
from core.functions.critique_answer import critique_answer
from core.functions.rerank_context import rerank_context
from core.functions.check_spelling import check_spelling
from core.functions.hierarchical_summarize import hierarchical_summarize
from core.utils.text_utils import count_tokens
logger = logging.getLogger(__name__)
@@ -208,31 +209,58 @@ class RAGOrchestrator:
f"промпт: {token_info['prompt_tokens']} токенов"
)
# ----- 4. Обрезка истории по токенам (с учётом лимита) -----
# Идём с конца (свежие сообщения) к началу, чтобы сохранить самые последние
truncated_history = []
total_history_tokens = 0
history_limit = min(available_for_history_and_context // 2, 2000) # выделяем половину для истории
# ----- 4. Обрезка истории (с использованием иерархического резюмирования) -----
max_history_tokens = min(available_for_history_and_context // 2, 2000)
for record in reversed(history):
tokens = count_tokens(record['content'])
if total_history_tokens + tokens <= history_limit:
truncated_history.append(record)
total_history_tokens += tokens
else:
break
truncated_history.reverse() # восстанавливаем хронологический порядок
# Преобразуем в формат, ожидаемый GigaChat
formatted_history = [
{"role": rec['role'], "content": rec['content']}
for rec in truncated_history
]
logger.debug(
f"История обрезана: {len(truncated_history)} сообщений, "
f"{total_history_tokens} токенов (лимит {history_limit})"
)
# Если история слишком длинная, сжимаем её иерархически
history_text = "\n".join([f"{rec['role']}: {rec['content']}" for rec in history])
if count_tokens(history_text) > max_history_tokens:
logger.info(f"История слишком длинная ({count_tokens(history_text)} токенов), применяем иерархическое резюмирование")
summary_prompt = prompts.get('hierarchical_summary', '')
if not summary_prompt:
# Загружаем из файла, если не передано
try:
with open(self.config.prompts_dir / 'hierarchical_summary.txt', 'r', encoding='utf-8') as f:
summary_prompt = f.read()
except Exception:
summary_prompt = "Кратко изложи суть диалога, сохранив ключевые факты и вопросы.\n\nТЕКСТ:\n{text}"
try:
compressed_history = await hierarchical_summarize(
text=history_text,
giga=self.giga,
prompt_template=summary_prompt,
target_tokens=max_history_tokens,
chunk_size_tokens=500,
max_depth=2,
temperature=getattr(self.config, 'ai_temperature', 0.1)
)
# Заменяем историю одним сжатым сообщением
formatted_history = [{"role": "system", "content": "Сжатая история диалога:\n" + compressed_history}]
logger.info(f"История сжата с {count_tokens(history_text)} до {count_tokens(compressed_history)} токенов")
except Exception as e:
logger.error(f"Ошибка при иерархическом резюмировании истории: {e}")
# Fallback: простая обрезка
truncated_history = []
total_tokens = 0
for record in reversed(history):
tokens = count_tokens(record['content'])
if total_tokens + tokens <= max_history_tokens:
truncated_history.append(record)
total_tokens += tokens
else:
break
truncated_history.reverse()
formatted_history = [
{"role": rec['role'], "content": rec['content']}
for rec in truncated_history
]
else:
# Если история укладывается, просто форматируем
truncated_history = history[-10:] # ограничим последними 10 сообщениями для простоты, но можно взять больше
formatted_history = [
{"role": rec['role'], "content": rec['content']}
for rec in truncated_history
]
# ----- 5. Классификация намерений (если не переопределена) -----
intent = intent_override