优化智能体体验

This commit is contained in:
Wenjie Zhang 2025-04-05 02:23:32 +08:00
parent 42384236f8
commit f5a7a3eec9
4 changed files with 127 additions and 40 deletions

View File

@ -174,21 +174,25 @@ def chat_agent(agent_name: str,
def stream_messages():
content = ""
yield make_chunk(status="init", meta=meta)
for msg, metadata in agent.stream_messages(messages, config_schema=runnable_config):
if isinstance(msg, AIMessageChunk) and msg.content != "<tool_call>":
content += msg.content
yield make_chunk(content=msg.content,
msg=msg.model_dump(),
metadata=metadata,
status="loading")
else:
yield make_chunk(msg=msg.model_dump(),
metadata=metadata,
status="loading")
try:
for msg, metadata in agent.stream_messages(messages, config_schema=runnable_config):
if isinstance(msg, AIMessageChunk) and msg.content != "<tool_call>":
content += msg.content
yield make_chunk(content=msg.content,
msg=msg.model_dump(),
metadata=metadata,
status="loading")
else:
yield make_chunk(msg=msg.model_dump(),
metadata=metadata,
status="loading")
yield make_chunk(status="finished",
history=history_manager.update_ai(content),
meta=meta)
yield make_chunk(status="finished",
history=history_manager.update_ai(content),
meta=meta)
except Exception as e:
logger.error(f"Error streaming messages: {e}")
yield make_chunk(message=f"Error streaming messages: {e}", status="error")
return StreamingResponse(stream_messages(), media_type='application/json')

View File

@ -444,6 +444,8 @@ const handleStreamResponse = async (response) => {
await handleInit(value);
} else if (value.status === 'finished') {
await handleFinished(value);
} else if (value.status === 'error') {
await handleError(value);
} else {
await handleMessageById(value);
}
@ -552,7 +554,7 @@ const handleFinished = async (data) => {
const handleMessageById = async (data) => {
const msgId = data.msg.id;
const msgType = data.msg.type;
// console.log("data", data);
console.log("data", data);
//
const existingMsgIndex = messageMap.value.get(msgId);
@ -678,11 +680,26 @@ const updateExistingMessage = async (data, existingMsgIndex) => {
}
}
// errorerror
if (data.status === 'error') {
msgInstance.status = 'error';
msgInstance.message = data.message;
}
//
await nextTick();
await scrollToBottom();
};
const handleError = async (data) => {
console.error('处理错误状态:', data);
const lastMsg = messages.value[messages.value.length - 1];
if (lastMsg) {
lastMsg.status = 'error';
lastMsg.message = data.message;
}
isProcessing.value = false;
};
const appendToolMessageToExistingAssistant = async (data) => {
// console.log("appendToolMessageToExistingAssistant", data);

View File

@ -42,7 +42,7 @@
<!-- 添加令牌弹窗 -->
<a-modal
v-model:visible="addTokenModalVisible"
v-model:open="addTokenModalVisible"
title="添加访问令牌"
ok-text="创建"
cancel-text="取消"

View File

@ -27,6 +27,34 @@
{{ agents[selectedAgentId]?.description }}
</p>
<!-- 添加配置按钮 -->
<div class="agent-action-buttons">
<a-button
class="action-button"
@click="openConfigModal"
>
<template #icon><SettingOutlined /></template>
智能体配置
</a-button>
<a-button
class="action-button"
@click="openTokenModal"
>
<template #icon><KeyOutlined /></template>
访问令牌
</a-button>
<a-button
class="action-button"
@click="goToAgentPage"
v-if="selectedAgentId"
>
<template #icon><LinkOutlined /></template>
打开独立页面
</a-button>
</div>
<!-- 添加requirements显示部分 -->
<div v-if="agents[selectedAgentId]?.requirements && agents[selectedAgentId]?.requirements.length > 0" class="info-section">
<h3>所需环境变量:</h3>
@ -62,12 +90,12 @@
<img src="@/assets/icons/sidebar_left.svg" class="iconfont icon-20" alt="设置" />
</div>
</template>
<template #header-right>
<!-- <template #header-right>
<div class="toggle-sidebar nav-btn" @click="toggleConfigSidebar()">
<SettingOutlined class="iconfont icon-20" />
<span class="text">配置</span>
</div>
</template>
</template> -->
</AgentChatComponent>
</div>
@ -80,33 +108,18 @@
</div>
</h2>
<div v-if="selectedAgentId" class="config-form">
<!-- 打开配置弹窗的按钮 -->
<a-button
type="primary"
block
@click="openConfigModal"
>
打开智能体配置
</a-button>
<!-- 添加令牌管理按钮 -->
<a-button
style="margin-top: 16px;"
type="primary"
block
@click="openTokenModal"
>
访问令牌管理
</a-button>
<!-- 已将按钮移至左侧边栏 -->
</div>
<div v-else class="no-agent-selected">
请先选择一个智能体
</div>
<p>你好智能体</p>
</div>
<!-- 配置弹窗 -->
<a-modal
v-model:visible="state.configModalVisible"
v-model:open="state.configModalVisible"
title="智能体配置"
width="650px"
:footer="null"
@ -162,7 +175,7 @@
<!-- 令牌管理弹窗 -->
<a-modal
v-model:visible="state.tokenModalVisible"
v-model:open="state.tokenModalVisible"
title="访问令牌管理"
width="650px"
:footer="null"
@ -175,17 +188,23 @@
<script setup>
import { ref, onMounted, reactive, watch, computed, h } from 'vue';
import { useRouter } from 'vue-router';
import {
RobotOutlined,
MenuFoldOutlined,
MenuUnfoldOutlined,
CloseOutlined,
SettingOutlined
SettingOutlined,
KeyOutlined,
LinkOutlined
} from '@ant-design/icons-vue';
import { message } from 'ant-design-vue';
import AgentChatComponent from '@/components/AgentChatComponent.vue';
import TokenManagerComponent from '@/components/TokenManagerComponent.vue';
//
const router = useRouter();
//
const agents = ref({});
const selectedAgentId = ref(null);
@ -323,7 +342,7 @@ const fetchAgents = async () => {
acc[agent.name] = agent;
return acc;
}, {});
console.log("agents", agents.value);
// console.log("agents", agents.value);
//
if (selectedAgentId.value) {
@ -392,6 +411,13 @@ const getPlaceholder = (key, value) => {
//
return `(默认: ${value.default}` ;
};
//
const goToAgentPage = () => {
if (selectedAgentId.value) {
window.open(`/agent/${selectedAgentId.value}`, '_blank');
}
};
</script>
<style lang="less" scoped>
@ -531,6 +557,22 @@ const getPlaceholder = (key, value) => {
.agent-info {
padding: 16px;
min-width: calc(var(--agent-sidebar-width) - 16px);
overflow-y: auto;
max-height: calc(100vh - 60px); /* 减去标题栏的高度 */
scrollbar-width: thin;
&::-webkit-scrollbar {
width: 4px;
}
&::-webkit-scrollbar-track {
background: transparent;
}
&::-webkit-scrollbar-thumb {
background-color: var(--main-light-4);
border-radius: 4px;
}
}
.agent-name {
@ -623,6 +665,30 @@ const getPlaceholder = (key, value) => {
gap: 10px;
}
}
//
.agent-action-buttons {
margin-top: 16px;
display: flex;
flex-direction: column;
gap: 8px;
}
.action-button {
background-color: white;
border: 1px solid var(--main-light-3);
text-align: left;
height: auto;
padding: 8px 12px;
&:hover {
background-color: var(--main-light-4);
}
.anticon {
margin-right: 8px;
}
}
</style>