Редактировать query_processor.py
This commit is contained in:
@@ -1,3 +1,7 @@
|
|||||||
|
# ============================================================
|
||||||
|
# rag/query_processor.py
|
||||||
|
# Полная версия с интеграцией всех новых функций
|
||||||
|
# ============================================================
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
"""
|
"""
|
||||||
Обработчик обычных RAG-запросов (FACT, PROCEDURE, COMPARISON, CALCULATION, GENERAL).
|
Обработчик обычных RAG-запросов (FACT, PROCEDURE, COMPARISON, CALCULATION, GENERAL).
|
||||||
@@ -9,6 +13,7 @@
|
|||||||
- Интеграция ReAct (вызов внешних инструментов)
|
- Интеграция ReAct (вызов внешних инструментов)
|
||||||
- Интеграция планирования действий (generate_plan)
|
- Интеграция планирования действий (generate_plan)
|
||||||
- Интеграция многоагентности (AgentCoordinator)
|
- Интеграция многоагентности (AgentCoordinator)
|
||||||
|
- Реальные обработчики инструментов (ToolHandler)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
@@ -30,6 +35,7 @@ from .functions.soma_evaluate import soma_evaluate
|
|||||||
from .functions.react import react_loop
|
from .functions.react import react_loop
|
||||||
from .functions.plan_generation import generate_plan
|
from .functions.plan_generation import generate_plan
|
||||||
from .agents.coordinator import AgentCoordinator
|
from .agents.coordinator import AgentCoordinator
|
||||||
|
from .functions.tools import ToolHandler
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -47,6 +53,7 @@ class QueryProcessor:
|
|||||||
config: AppConfig,
|
config: AppConfig,
|
||||||
default_prompts: Optional[Dict[str, str]] = None,
|
default_prompts: Optional[Dict[str, str]] = None,
|
||||||
agent_coordinator: Optional[AgentCoordinator] = None,
|
agent_coordinator: Optional[AgentCoordinator] = None,
|
||||||
|
tool_handler: Optional[ToolHandler] = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""
|
"""
|
||||||
Инициализация QueryProcessor.
|
Инициализация QueryProcessor.
|
||||||
@@ -57,6 +64,7 @@ class QueryProcessor:
|
|||||||
config: конфигурация приложения.
|
config: конфигурация приложения.
|
||||||
default_prompts: словарь промптов по умолчанию.
|
default_prompts: словарь промптов по умолчанию.
|
||||||
agent_coordinator: координатор агентов (если включена многоагентность).
|
agent_coordinator: координатор агентов (если включена многоагентность).
|
||||||
|
tool_handler: обработчик инструментов для ReAct.
|
||||||
"""
|
"""
|
||||||
self.giga: GigaClient = giga
|
self.giga: GigaClient = giga
|
||||||
self.kb: KBService = kb
|
self.kb: KBService = kb
|
||||||
@@ -64,6 +72,7 @@ class QueryProcessor:
|
|||||||
self.default_prompts: Dict[str, str] = default_prompts or {}
|
self.default_prompts: Dict[str, str] = default_prompts or {}
|
||||||
self.prompt_builder: PromptBuilder = PromptBuilder(config)
|
self.prompt_builder: PromptBuilder = PromptBuilder(config)
|
||||||
self.agent_coordinator: Optional[AgentCoordinator] = agent_coordinator
|
self.agent_coordinator: Optional[AgentCoordinator] = agent_coordinator
|
||||||
|
self.tool_handler: Optional[ToolHandler] = tool_handler
|
||||||
|
|
||||||
def _needs_external_data(self, query: str) -> bool:
|
def _needs_external_data(self, query: str) -> bool:
|
||||||
"""
|
"""
|
||||||
@@ -77,22 +86,34 @@ class QueryProcessor:
|
|||||||
def _get_available_tools(self) -> List[Dict[str, Any]]:
|
def _get_available_tools(self) -> List[Dict[str, Any]]:
|
||||||
"""
|
"""
|
||||||
Возвращает список доступных инструментов для ReAct.
|
Возвращает список доступных инструментов для ReAct.
|
||||||
В реальности инструменты определяются в конфиге и регистрируются в приложении.
|
Использует реальные обработчики из ToolHandler, если он доступен.
|
||||||
Здесь возвращаем заглушку, которая должна быть переопределена в рантайме.
|
|
||||||
"""
|
"""
|
||||||
# В будущем можно загружать из конфига: getattr(self.config, 'react_tools', [])
|
if self.tool_handler is None:
|
||||||
|
return []
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
"name": "search",
|
"name": "search",
|
||||||
"description": "Поиск информации в интернете",
|
"description": "Поиск информации в интернете по запросу",
|
||||||
"parameters": {"query": "string"},
|
"parameters": {"query": "string"},
|
||||||
"handler": None # будет передан извне (например, через регистрацию)
|
"handler": self.tool_handler.search
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "get_weather",
|
"name": "get_weather",
|
||||||
"description": "Получить текущую погоду в городе",
|
"description": "Получить текущую погоду в городе",
|
||||||
"parameters": {"city": "string"},
|
"parameters": {"city": "string"},
|
||||||
"handler": None
|
"handler": self.tool_handler.get_weather
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "book_flight",
|
||||||
|
"description": "Забронировать авиабилет (заглушка)",
|
||||||
|
"parameters": {"origin": "string", "destination": "string", "date": "string"},
|
||||||
|
"handler": self.tool_handler.book_flight
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "get_exchange_rate",
|
||||||
|
"description": "Получить курс валют (заглушка)",
|
||||||
|
"parameters": {"from_currency": "string", "to_currency": "string"},
|
||||||
|
"handler": self.tool_handler.get_exchange_rate
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -129,12 +150,11 @@ class QueryProcessor:
|
|||||||
self.agent_coordinator is not None):
|
self.agent_coordinator is not None):
|
||||||
logger.info("Запрос передан в AgentCoordinator")
|
logger.info("Запрос передан в AgentCoordinator")
|
||||||
try:
|
try:
|
||||||
# Пытаемся обработать запрос через агентов
|
|
||||||
agent_result = await self.agent_coordinator.process(
|
agent_result = await self.agent_coordinator.process(
|
||||||
query=query,
|
query=query,
|
||||||
context="", # агенты сами ищут контекст (или используют свой)
|
context="",
|
||||||
history=history,
|
history=history,
|
||||||
tools=None # можно передать общие инструменты
|
tools=None
|
||||||
)
|
)
|
||||||
if agent_result:
|
if agent_result:
|
||||||
logger.info("AgentCoordinator вернул ответ")
|
logger.info("AgentCoordinator вернул ответ")
|
||||||
@@ -156,7 +176,7 @@ class QueryProcessor:
|
|||||||
)
|
)
|
||||||
search_query: str = expanded if expanded and expanded != query else query
|
search_query: str = expanded if expanded and expanded != query else query
|
||||||
|
|
||||||
# ---- 3. Поиск релевантного контекста в базе знаний ----
|
# ---- 3. Поиск релевантного контекста ----
|
||||||
context: str = await self.kb.find_relevant_info(
|
context: str = await self.kb.find_relevant_info(
|
||||||
search_query, user_jid, room_jid,
|
search_query, user_jid, room_jid,
|
||||||
top_k=getattr(self.config, 'rag_default_top_k', 30)
|
top_k=getattr(self.config, 'rag_default_top_k', 30)
|
||||||
@@ -177,7 +197,7 @@ class QueryProcessor:
|
|||||||
else:
|
else:
|
||||||
context = ""
|
context = ""
|
||||||
|
|
||||||
# ---- 5. Переранжирование контекста ----
|
# ---- 5. Переранжирование ----
|
||||||
rerank_min_length: int = getattr(self.config, 'rerank_min_length', 5000)
|
rerank_min_length: int = getattr(self.config, 'rerank_min_length', 5000)
|
||||||
if intent != "FACT" and len(context) > rerank_min_length:
|
if intent != "FACT" and len(context) > rerank_min_length:
|
||||||
context = await rerank_context(
|
context = await rerank_context(
|
||||||
@@ -203,7 +223,7 @@ class QueryProcessor:
|
|||||||
logger.info(f"Сгенерирован план из {len(plan)} шагов")
|
logger.info(f"Сгенерирован план из {len(plan)} шагов")
|
||||||
extra_instructions = f"Выполни следующие шаги по порядку: {json.dumps(plan, ensure_ascii=False)}"
|
extra_instructions = f"Выполни следующие шаги по порядку: {json.dumps(plan, ensure_ascii=False)}"
|
||||||
|
|
||||||
# ---- 7. Формирование промта (с учётом возможного плана) ----
|
# ---- 7. Формирование промта ----
|
||||||
if intent in ("CALCULATION", "PROCEDURE") and not extra_instructions:
|
if intent in ("CALCULATION", "PROCEDURE") and not extra_instructions:
|
||||||
extra_instructions = (
|
extra_instructions = (
|
||||||
"Пожалуйста, покажи пошаговое решение перед итоговым ответом. "
|
"Пожалуйста, покажи пошаговое решение перед итоговым ответом. "
|
||||||
@@ -223,7 +243,7 @@ class QueryProcessor:
|
|||||||
system_prompt=system_prompt,
|
system_prompt=system_prompt,
|
||||||
extra_instructions=extra_instructions
|
extra_instructions=extra_instructions
|
||||||
)
|
)
|
||||||
logger.debug(f"Сформированный промт (первые 500 символов): {prompt[:500]}")
|
logger.debug(f"Сформирован промт (первые 500 символов): {prompt[:500]}")
|
||||||
|
|
||||||
# ---- 8. Генерация ответа ----
|
# ---- 8. Генерация ответа ----
|
||||||
answer: str = await self.giga.chat(
|
answer: str = await self.giga.chat(
|
||||||
@@ -240,9 +260,6 @@ class QueryProcessor:
|
|||||||
logger.info("Запрос требует внешних данных, запускаем ReAct цикл")
|
logger.info("Запрос требует внешних данных, запускаем ReAct цикл")
|
||||||
try:
|
try:
|
||||||
tools = self._get_available_tools()
|
tools = self._get_available_tools()
|
||||||
# В реальности нужно передать реальные обработчики инструментов.
|
|
||||||
# Здесь они могут быть зарегистрированы в конфиге.
|
|
||||||
# Для демонстрации мы пытаемся вызвать react_loop.
|
|
||||||
react_answer = await react_loop(
|
react_answer = await react_loop(
|
||||||
query=query,
|
query=query,
|
||||||
history=history,
|
history=history,
|
||||||
@@ -306,7 +323,6 @@ class QueryProcessor:
|
|||||||
threshold = getattr(self.config, 'soma_threshold', 3.5)
|
threshold = getattr(self.config, 'soma_threshold', 3.5)
|
||||||
if evaluation.get('overall_score', 0) < threshold:
|
if evaluation.get('overall_score', 0) < threshold:
|
||||||
logger.warning(f"SOMA оценка низкая ({evaluation['overall_score']}), перегенерация")
|
logger.warning(f"SOMA оценка низкая ({evaluation['overall_score']}), перегенерация")
|
||||||
# Перегенерация с повышенной температурой для разнообразия
|
|
||||||
answer = await self.giga.chat(
|
answer = await self.giga.chat(
|
||||||
history=[],
|
history=[],
|
||||||
query=prompt,
|
query=prompt,
|
||||||
@@ -314,7 +330,6 @@ class QueryProcessor:
|
|||||||
file_id=None,
|
file_id=None,
|
||||||
temperature=0.3
|
temperature=0.3
|
||||||
)
|
)
|
||||||
# Вторая оценка (опционально)
|
|
||||||
evaluation2 = await soma_evaluate(
|
evaluation2 = await soma_evaluate(
|
||||||
query=query,
|
query=query,
|
||||||
context=context,
|
context=context,
|
||||||
@@ -342,3 +357,9 @@ class QueryProcessor:
|
|||||||
"sources": list(set(sources)),
|
"sources": list(set(sources)),
|
||||||
"confidence": None
|
"confidence": None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async def close(self) -> None:
|
||||||
|
"""Закрывает ресурсы (HTTP-сессию ToolHandler)."""
|
||||||
|
if self.tool_handler:
|
||||||
|
await self.tool_handler.close()
|
||||||
|
logger.info("ToolHandler закрыт")
|
||||||
Reference in New Issue
Block a user