From ede78ad3900119e507718557e2f4c2856803d9f5 Mon Sep 17 00:00:00 2001 From: Wenjie Zhang Date: Wed, 9 Apr 2025 11:47:08 +0800 Subject: [PATCH] fix agent talk bug and add some error traceback --- server/routers/chat_router.py | 48 +++++++++++----------- src/agents/registry.py | 3 +- src/models/chat_model.py | 50 +++++++++++++++++++++-- web/src/components/AgentChatComponent.vue | 12 ++++++ web/src/components/MessageComponent.vue | 2 +- 5 files changed, 87 insertions(+), 28 deletions(-) diff --git a/server/routers/chat_router.py b/server/routers/chat_router.py index ad691346..b10945c4 100644 --- a/server/routers/chat_router.py +++ b/server/routers/chat_router.py @@ -171,32 +171,34 @@ def chat_agent(agent_name: str, **kwargs }, ensure_ascii=False).encode('utf-8') + b"\n" - try: - agent = agent_manager.get_runnable_agent(agent_name) - except Exception as e: - logger.error(f"Error getting agent {agent_name}: {e}") - return StreamingResponse(make_chunk(message=f"Error getting agent {agent_name}: {e}", status="error"), media_type='application/json') - # 从config中获取history_round - history_round = config.get("history_round") - history_manager = HistoryManager(history) - messages = history_manager.get_history_with_msg(query, max_rounds=history_round) - history_manager.add_user(query) - - # 如果没有thread_id则生成一个 - if "thread_id" not in config or not config["thread_id"]: - config["thread_id"] = str(uuid.uuid4()) - - # 构造运行时配置 - runnable_config = { - "configurable": { - **config - } - } def stream_messages(): - content = "" + + # 代表服务端已经收到了请求 yield make_chunk(status="init", meta=meta) + + try: + agent = agent_manager.get_runnable_agent(agent_name) + except Exception as e: + logger.error(f"Error getting agent {agent_name}: {e}, {traceback.format_exc()}") + yield make_chunk(message=f"Error getting agent {agent_name}: {e}", status="error") + return + + # 从config中获取history_round + history_round = config.get("history_round") + history_manager = HistoryManager(history) + messages = history_manager.get_history_with_msg(query, max_rounds=history_round) + history_manager.add_user(query) + + # 构造运行时配置,如果没有thread_id则生成一个 + if "thread_id" not in config or not config["thread_id"]: + config["thread_id"] = str(uuid.uuid4()) + + runnable_config = {"configurable": {**config}} + + content = "" + try: for msg, metadata in agent.stream_messages(messages, config_schema=runnable_config): if isinstance(msg, AIMessageChunk) and msg.content != "": @@ -214,7 +216,7 @@ def chat_agent(agent_name: str, history=history_manager.update_ai(content), meta=meta) except Exception as e: - logger.error(f"Error streaming messages: {e}") + logger.error(f"Error streaming messages: {e}, {traceback.format_exc()}") yield make_chunk(message=f"Error streaming messages: {e}", status="error") return StreamingResponse(stream_messages(), media_type='application/json') diff --git a/src/agents/registry.py b/src/agents/registry.py index dc974bd7..8bca8399 100644 --- a/src/agents/registry.py +++ b/src/agents/registry.py @@ -3,6 +3,7 @@ from __future__ import annotations import os from typing import Type, Annotated, Optional, TypedDict +from enum import Enum from abc import abstractmethod from dataclasses import dataclass, fields, field @@ -96,7 +97,7 @@ class BaseAgent(): return for requirement in self.requirements: if requirement not in os.environ: - raise ValueError(f"{requirement} is not set") + raise ValueError(f"没有配置{requirement} 环境变量,请在 src/.env 文件中配置") def stream_values(self, messages: list[str], config_schema: RunnableConfig = None, **kwargs): graph = self.get_graph(config_schema=config_schema, **kwargs) diff --git a/src/models/chat_model.py b/src/models/chat_model.py index 065d9e36..0aacd6f6 100644 --- a/src/models/chat_model.py +++ b/src/models/chat_model.py @@ -1,18 +1,19 @@ import os +import requests from openai import OpenAI from src.utils import logger, get_docker_safe_url from langchain_openai import ChatOpenAI class OpenAIBase(): - def __init__(self, api_key, base_url, model_name): + def __init__(self, api_key, base_url, model_name, **kwargs): self.api_key = api_key self.base_url = base_url self.client = OpenAI(api_key=api_key, base_url=base_url) self.model_name = model_name + self.info = kwargs self.chat_open_ai = ChatOpenAI(model=model_name, api_key=api_key, - base_url=base_url, - temperature=0.7) + base_url=base_url) def predict(self, message, stream=False): if isinstance(message, str): @@ -54,6 +55,49 @@ class OpenAIBase(): logger.error(f"Error getting models: {e}") return [] + def _get_model_by_model_url(self, model_url): + """ + Refs: https://docs.together.ai/reference/models-1 + + Return: [ + { + "id": "meta-llama/Meta-Llama-3-70B-Instruct-Turbo", + "object": "model", + "created": 0, + "type": "chat", + "running": false, + "display_name": "Meta Llama 3 70B Instruct Turbo", + "organization": "Meta", + "link": "https://huggingface.co/meta-llama/Meta-Llama-3-70B-Instruct", + "license": "Llama-3 (Other)", + "context_length": 8192, + "config": { + "chat_template": "{% set loop_messages = messages %}{% for message in loop_messages %}{% set content = '<|start_header_id|>' + message['role'] + '<|end_header_id|>\n\n'+ message['content'] | trim + '<|eot_id|>' %}{% if loop.index0 == 0 %}{% set content = bos_token + content %}{% endif %}{{ content }}{% endfor %}{{ '<|start_header_id|>assistant<|end_header_id|>\n\n' }}", + "stop": [ + "<|eot_id|>" + ], + "bos_token": "<|begin_of_text|>", + "eos_token": "<|end_of_text|>" + }, + "pricing": { + "hourly": 0, + "input": 0.88, + "output": 0.88, + "base": 0, + "finetune": 0 + } + }, + ] + + """ + headers = { + "accept": "application/json", + "authorization": f"Bearer {self.api_key}" + } + response = requests.get(model_url, headers=headers) + return response.json() + + class OpenModel(OpenAIBase): def __init__(self, model_name=None): diff --git a/web/src/components/AgentChatComponent.vue b/web/src/components/AgentChatComponent.vue index d1e072cc..5272d74b 100644 --- a/web/src/components/AgentChatComponent.vue +++ b/web/src/components/AgentChatComponent.vue @@ -511,6 +511,18 @@ const handleStreamResponse = async (response) => { } } catch (error) { console.error('流式处理出错:', error); + const lastMsg = messages.value[messages.value.length - 1]; + if (lastMsg.role === 'assistant') { + lastMsg.status = 'error'; + lastMsg.message = error.message; + } else { + messages.value.push({ + role: 'assistant', + message: `发生错误: ${error.message}`, + status: 'error' + }); + await scrollToBottom(); + } isProcessing.value = false; } }; diff --git a/web/src/components/MessageComponent.vue b/web/src/components/MessageComponent.vue index 1a5d0a88..09d1a088 100644 --- a/web/src/components/MessageComponent.vue +++ b/web/src/components/MessageComponent.vue @@ -48,7 +48,7 @@ previewTheme="github" :showCodeRowNumber="false" :modelValue="message.content" - :key="index" + :key="message.id" class="message-md"/>