diff --git a/docs/changelog/update.md b/docs/changelog/update.md
index e2c213ed..fc34bf9a 100644
--- a/docs/changelog/update.md
+++ b/docs/changelog/update.md
@@ -1,7 +1,7 @@
目前已有的开发计划包括:
💭 **Features Todo**
-- [ ] LangGraph 升级到 0.6+ 版本,并适配新特性,如 context 等,添加 MCP 工具的支持。
+- [x] LangGraph 升级到 0.6+ 版本,并适配新特性,如 context 等,添加 MCP 工具的支持。
- [x] 支持动态工具配置的同时,将 Configuration替换为 Context 后能够正常使用
- [ ] 使用更好的知识图谱检索方法
- [ ] 使用其他的聊天记录管理方法,解决两个问题,一个是上下文长度过长,一个是上下文的类型变得更加丰富,比如多模态等等。(现在是基于 LangGraph 的 Memory 实现的,v0.2.3 版本实现),暂定使用 [mem0](github.com/mem0ai/mem0) 来实现。但是目前了解下来,还不是我想要的那种方案。可能会基于这个实现一个 ThreadConvManager 这个类。
@@ -24,7 +24,7 @@
下面的功能**可能**会放在后续版本实现,暂时未定
- [ ] 支持数据库查询功能
-- [ ] 消息内容支持图片显示
+- [x] 消息内容支持图片显示
- [ ] 添加 SQL 读取工具
- [ ] 添加绘图工具(这里的绘图是指绘制固定格式的图和表等,暂时没想好如何支持自定义绘图)
- [ ] 添加测试脚本,覆盖最常见的功能
diff --git a/server/routers/chat_router.py b/server/routers/chat_router.py
index 0b8d16b0..eb17a680 100644
--- a/server/routers/chat_router.py
+++ b/server/routers/chat_router.py
@@ -2,6 +2,8 @@ import asyncio
import json
import traceback
import uuid
+import yaml
+from pathlib import Path
from fastapi import APIRouter, Body, Depends, HTTPException
from fastapi.responses import StreamingResponse
@@ -97,7 +99,11 @@ async def get_agent(current_user: User = Depends(get_required_user)):
"""获取所有可用智能体(需要登录)"""
agents = await agent_manager.get_agents_info()
# logger.debug(f"agents: {agents}")
- return {"agents": agents}
+ metadata = {}
+ if Path("src/static/agents_meta.yaml").exists():
+ with open("src/static/agents_meta.yaml") as f:
+ metadata = yaml.safe_load(f)
+ return {"agents": agents, "metadata": metadata}
@chat.post("/agent/{agent_id}")
diff --git a/src/static/agents_meta.yaml b/src/static/agents_meta.yaml
new file mode 100644
index 00000000..2d03a4be
--- /dev/null
+++ b/src/static/agents_meta.yaml
@@ -0,0 +1,9 @@
+ChatbotAgent:
+ name: 食品安全知识助手
+ icon: /agents-icon/chatbot.png
+ examples:
+ - 冰箱里不同食材应该怎么存放?
+ - 有机食品和普通食品有什么区别?
+ - 外卖食品安全需要注意什么?
+ - 如何判断食品是否已经变质?
+ - 食品添加剂对健康有害吗?
\ No newline at end of file
diff --git a/web/public/agents-icon/chatbot.png b/web/public/agents-icon/chatbot.png
new file mode 100644
index 00000000..322ca76e
Binary files /dev/null and b/web/public/agents-icon/chatbot.png differ
diff --git a/web/src/components/AgentChatComponent.vue b/web/src/components/AgentChatComponent.vue
index afa1b1f8..17c825fe 100644
--- a/web/src/components/AgentChatComponent.vue
+++ b/web/src/components/AgentChatComponent.vue
@@ -60,8 +60,12 @@
-
{{ currentAgent ? currentAgent.name : '请选择一个智能体开始对话' }}
-
{{ currentAgent ? currentAgent.description : '不同的智能体有不同的专长和能力' }}
+
![智能体图标]()
+
+
您好,我是{{ currentAgentName }}!有什么可以帮您?
+
+
@@ -164,6 +183,15 @@ const {
// ==================== LOCAL CHAT & UI STATE ====================
const userInput = ref('');
+// 从智能体元数据获取示例问题
+const exampleQuestions = computed(() => {
+ const examples = currentAgentMetadata.value?.examples || [];
+ return examples.map((text, index) => ({
+ id: index + 1,
+ text: text
+ }));
+});
+
const chatState = reactive({
currentThreadId: null,
isLoadingThreads: false,
@@ -195,6 +223,9 @@ const currentAgentId = computed(() => {
}
});
+const currentAgentMetadata = computed(() => agentStore.metadata[currentAgentId.value] || {});
+const currentAgentName = computed(() => currentAgentMetadata?.value.name || currentAgent.name || '智能体');
+
const currentAgent = computed(() => agents.value[currentAgentId.value] || null);
const chatsList = computed(() => threads.value || []);
const currentChatId = computed(() => chatState.currentThreadId);
@@ -674,6 +705,14 @@ const handleKeyDown = (e) => {
}
};
+// 处理示例问题点击
+const handleExampleClick = (questionText) => {
+ userInput.value = questionText;
+ nextTick(() => {
+ handleSendMessage();
+ });
+};
+
const shareChat = async () => {
if (!AgentValidator.validateShareOperation(currentChatId.value, currentAgent.value, handleValidationError)) return;
try {
@@ -926,7 +965,7 @@ watch(conversations, () => {
padding: 0 50px;
text-align: center;
position: absolute;
- top: 20%;
+ top: 15%;
width: 100%;
z-index: 9;
animation: slideInUp 0.5s ease-out;
@@ -942,8 +981,58 @@ watch(conversations, () => {
color: var(--gray-700);
}
+ .agent-icons {
+ height: 180px;
+ }
+
+ .example-questions {
+ margin-top: 16px;
+ text-align: center;
+
+ .example-title {
+ font-size: 0.85rem;
+ color: var(--gray-600);
+ margin-bottom: 12px;
+ }
+
+ .example-chips {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 8px;
+ justify-content: center;
+ }
+
+ .example-chip {
+ padding: 6px 12px;
+ background: var(--gray-100);
+ border: 1px solid var(--gray-200);
+ border-radius: 16px;
+ cursor: pointer;
+ font-size: 0.8rem;
+ color: var(--gray-700);
+ transition: all 0.15s ease;
+ white-space: nowrap;
+ max-width: 200px;
+ overflow: hidden;
+ text-overflow: ellipsis;
+
+ &:hover {
+ background: var(--main-50);
+ border-color: var(--main-200);
+ color: var(--main-700);
+ transform: translateY(-1px);
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+ }
+
+ &:active {
+ transform: translateY(0);
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
+ }
+ }
+ }
+
.inputer-init {
- margin: 40px auto;
+ margin: 20px auto;
width: 90%;
max-width: 800px;
}
diff --git a/web/src/stores/agent.js b/web/src/stores/agent.js
index 806ebfa6..6f882155 100644
--- a/web/src/stores/agent.js
+++ b/web/src/stores/agent.js
@@ -7,6 +7,7 @@ export const useAgentStore = defineStore('agent', {
state: () => ({
// 智能体相关状态
agents: {}, // 以ID为键的智能体对象
+ metadata: {}, // 智能体元数据
selectedAgentId: null, // 当前选中的智能体ID
defaultAgentId: null, // 默认智能体ID
@@ -102,6 +103,7 @@ export const useAgentStore = defineStore('agent', {
acc[agent.id] = agent;
return acc;
}, {});
+ this.metadata = response.metadata;
} catch (error) {
console.error('Failed to fetch agents:', error);
handleChatError(error, 'fetch');