feat: restore source parity and harden agent runtime

This commit is contained in:
2026-06-22 11:17:26 +08:00
parent e33f08277b
commit 0793eb82d6
596 changed files with 168879 additions and 290 deletions
@@ -570,7 +570,7 @@ class ConfirmNode(BaseNode):
return False, False
def _llm_intent_recognition(self, user_input: str, context_content: str, model_id: str) -> bool:
def _llm_intent_recognition(self, user_input: str, context_content: str, model_id: str, db_session=None) -> bool:
"""
使用 LLM 进行意图识别
@@ -595,7 +595,7 @@ class ConfirmNode(BaseNode):
请判断用户意图:"""
llm_service = LLMService()
llm_service = LLMService(db_session)
response = llm_service.chat(
model_id=model_id,
messages=[
@@ -639,7 +639,9 @@ class ConfirmNode(BaseNode):
if not matched and use_llm_intent and llm_model_id:
# 关键词未匹配,使用 LLM 意图识别
logger.info(f'关键词未匹配,使用 LLM 意图识别: {user_input}')
confirmed = self._llm_intent_recognition(str(user_input), content, llm_model_id)
confirmed = self._llm_intent_recognition(
str(user_input), content, llm_model_id, context.db_session
)
elif not matched:
# 关键词未匹配且未启用 LLM,默认为取消
logger.info(f'关键词未匹配,默认取消: {user_input}')
@@ -313,6 +313,7 @@ class LLMNode(BaseNode):
messages.append({'role': 'user', 'content': user_prompt})
llm_service = LLMService(context.db_session)
model_id = llm_service.resolve_chat_model_id_sync(model_id)
output_var = self.config.get('output_variable', 'llm_response')
# 根据输出模式选择执行方式
@@ -64,6 +64,26 @@ class LLMService:
logger.info("No model_id supplied, fallback to default chat model %s", model.id)
return str(model.id)
@staticmethod
def _run_async_sync(coro):
import asyncio
import concurrent.futures
try:
loop = asyncio.get_event_loop()
except RuntimeError:
return asyncio.run(coro)
if loop.is_running():
with concurrent.futures.ThreadPoolExecutor() as executor:
return executor.submit(asyncio.run, coro).result()
return loop.run_until_complete(coro)
def resolve_chat_model_id_sync(self, model_id: Optional[str]) -> str:
"""同步解析 chat 模型,供同步节点和流式生成器复用。"""
return self._run_async_sync(self.resolve_chat_model_id(model_id))
async def _get_provider_async(self, model_id: str) -> tuple:
"""
@@ -272,6 +292,34 @@ class LLMService:
return provider.chat(llm_messages, config)
except Exception as exc:
raise RuntimeError(self._format_provider_error(exc, provider, model_name)) from exc
def chat(
self,
model_id: Optional[str],
messages: List[Dict[str, str]],
temperature: float = 0.7,
max_tokens: int = 2048,
tools: List[Dict] = None,
tool_choice: str = 'auto',
**kwargs
) -> LLMResponse:
"""
同步对话入口。
旧节点仍会调用该方法;这里统一走 provider 解析和默认 chat 模型兜底,
避免不同节点各自处理 model_id 为空的情况。
"""
provider, model_name = self._run_async_sync(self._get_provider_async(model_id))
return self.chat_with_provider(
provider=provider,
model_name=model_name,
messages=messages,
temperature=temperature,
max_tokens=max_tokens,
tools=tools,
tool_choice=tool_choice,
**kwargs,
)
def _convert_messages(self, messages: List[Dict]) -> List[LLMMessage]:
"""转换消息格式,支持 tool 消息"""