优化智能体体验
This commit is contained in:
parent
42384236f8
commit
f5a7a3eec9
@ -174,21 +174,25 @@ def chat_agent(agent_name: str,
|
|||||||
def stream_messages():
|
def stream_messages():
|
||||||
content = ""
|
content = ""
|
||||||
yield make_chunk(status="init", meta=meta)
|
yield make_chunk(status="init", meta=meta)
|
||||||
for msg, metadata in agent.stream_messages(messages, config_schema=runnable_config):
|
try:
|
||||||
if isinstance(msg, AIMessageChunk) and msg.content != "<tool_call>":
|
for msg, metadata in agent.stream_messages(messages, config_schema=runnable_config):
|
||||||
content += msg.content
|
if isinstance(msg, AIMessageChunk) and msg.content != "<tool_call>":
|
||||||
yield make_chunk(content=msg.content,
|
content += msg.content
|
||||||
msg=msg.model_dump(),
|
yield make_chunk(content=msg.content,
|
||||||
metadata=metadata,
|
msg=msg.model_dump(),
|
||||||
status="loading")
|
metadata=metadata,
|
||||||
else:
|
status="loading")
|
||||||
yield make_chunk(msg=msg.model_dump(),
|
else:
|
||||||
metadata=metadata,
|
yield make_chunk(msg=msg.model_dump(),
|
||||||
status="loading")
|
metadata=metadata,
|
||||||
|
status="loading")
|
||||||
|
|
||||||
yield make_chunk(status="finished",
|
yield make_chunk(status="finished",
|
||||||
history=history_manager.update_ai(content),
|
history=history_manager.update_ai(content),
|
||||||
meta=meta)
|
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')
|
return StreamingResponse(stream_messages(), media_type='application/json')
|
||||||
|
|
||||||
|
|||||||
@ -444,6 +444,8 @@ const handleStreamResponse = async (response) => {
|
|||||||
await handleInit(value);
|
await handleInit(value);
|
||||||
} else if (value.status === 'finished') {
|
} else if (value.status === 'finished') {
|
||||||
await handleFinished(value);
|
await handleFinished(value);
|
||||||
|
} else if (value.status === 'error') {
|
||||||
|
await handleError(value);
|
||||||
} else {
|
} else {
|
||||||
await handleMessageById(value);
|
await handleMessageById(value);
|
||||||
}
|
}
|
||||||
@ -552,7 +554,7 @@ const handleFinished = async (data) => {
|
|||||||
const handleMessageById = async (data) => {
|
const handleMessageById = async (data) => {
|
||||||
const msgId = data.msg.id;
|
const msgId = data.msg.id;
|
||||||
const msgType = data.msg.type;
|
const msgType = data.msg.type;
|
||||||
// console.log("data", data);
|
console.log("data", data);
|
||||||
|
|
||||||
// 查找现有消息
|
// 查找现有消息
|
||||||
const existingMsgIndex = messageMap.value.get(msgId);
|
const existingMsgIndex = messageMap.value.get(msgId);
|
||||||
@ -678,11 +680,26 @@ const updateExistingMessage = async (data, existingMsgIndex) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 如果状态是error,则更新为error
|
||||||
|
if (data.status === 'error') {
|
||||||
|
msgInstance.status = 'error';
|
||||||
|
msgInstance.message = data.message;
|
||||||
|
}
|
||||||
|
|
||||||
// 确保变更生效
|
// 确保变更生效
|
||||||
await nextTick();
|
await nextTick();
|
||||||
await scrollToBottom();
|
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) => {
|
const appendToolMessageToExistingAssistant = async (data) => {
|
||||||
// console.log("appendToolMessageToExistingAssistant", data);
|
// console.log("appendToolMessageToExistingAssistant", data);
|
||||||
|
|||||||
@ -42,7 +42,7 @@
|
|||||||
|
|
||||||
<!-- 添加令牌弹窗 -->
|
<!-- 添加令牌弹窗 -->
|
||||||
<a-modal
|
<a-modal
|
||||||
v-model:visible="addTokenModalVisible"
|
v-model:open="addTokenModalVisible"
|
||||||
title="添加访问令牌"
|
title="添加访问令牌"
|
||||||
ok-text="创建"
|
ok-text="创建"
|
||||||
cancel-text="取消"
|
cancel-text="取消"
|
||||||
|
|||||||
@ -27,6 +27,34 @@
|
|||||||
{{ agents[selectedAgentId]?.description }}
|
{{ agents[selectedAgentId]?.description }}
|
||||||
</p>
|
</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显示部分 -->
|
<!-- 添加requirements显示部分 -->
|
||||||
<div v-if="agents[selectedAgentId]?.requirements && agents[selectedAgentId]?.requirements.length > 0" class="info-section">
|
<div v-if="agents[selectedAgentId]?.requirements && agents[selectedAgentId]?.requirements.length > 0" class="info-section">
|
||||||
<h3>所需环境变量:</h3>
|
<h3>所需环境变量:</h3>
|
||||||
@ -62,12 +90,12 @@
|
|||||||
<img src="@/assets/icons/sidebar_left.svg" class="iconfont icon-20" alt="设置" />
|
<img src="@/assets/icons/sidebar_left.svg" class="iconfont icon-20" alt="设置" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #header-right>
|
<!-- <template #header-right>
|
||||||
<div class="toggle-sidebar nav-btn" @click="toggleConfigSidebar()">
|
<div class="toggle-sidebar nav-btn" @click="toggleConfigSidebar()">
|
||||||
<SettingOutlined class="iconfont icon-20" />
|
<SettingOutlined class="iconfont icon-20" />
|
||||||
<span class="text">配置</span>
|
<span class="text">配置</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template> -->
|
||||||
</AgentChatComponent>
|
</AgentChatComponent>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -80,33 +108,18 @@
|
|||||||
</div>
|
</div>
|
||||||
</h2>
|
</h2>
|
||||||
<div v-if="selectedAgentId" class="config-form">
|
<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>
|
||||||
<div v-else class="no-agent-selected">
|
<div v-else class="no-agent-selected">
|
||||||
请先选择一个智能体
|
请先选择一个智能体
|
||||||
</div>
|
</div>
|
||||||
|
<p>你好,智能体</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<!-- 配置弹窗 -->
|
<!-- 配置弹窗 -->
|
||||||
<a-modal
|
<a-modal
|
||||||
v-model:visible="state.configModalVisible"
|
v-model:open="state.configModalVisible"
|
||||||
title="智能体配置"
|
title="智能体配置"
|
||||||
width="650px"
|
width="650px"
|
||||||
:footer="null"
|
:footer="null"
|
||||||
@ -162,7 +175,7 @@
|
|||||||
|
|
||||||
<!-- 令牌管理弹窗 -->
|
<!-- 令牌管理弹窗 -->
|
||||||
<a-modal
|
<a-modal
|
||||||
v-model:visible="state.tokenModalVisible"
|
v-model:open="state.tokenModalVisible"
|
||||||
title="访问令牌管理"
|
title="访问令牌管理"
|
||||||
width="650px"
|
width="650px"
|
||||||
:footer="null"
|
:footer="null"
|
||||||
@ -175,17 +188,23 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onMounted, reactive, watch, computed, h } from 'vue';
|
import { ref, onMounted, reactive, watch, computed, h } from 'vue';
|
||||||
|
import { useRouter } from 'vue-router';
|
||||||
import {
|
import {
|
||||||
RobotOutlined,
|
RobotOutlined,
|
||||||
MenuFoldOutlined,
|
MenuFoldOutlined,
|
||||||
MenuUnfoldOutlined,
|
MenuUnfoldOutlined,
|
||||||
CloseOutlined,
|
CloseOutlined,
|
||||||
SettingOutlined
|
SettingOutlined,
|
||||||
|
KeyOutlined,
|
||||||
|
LinkOutlined
|
||||||
} from '@ant-design/icons-vue';
|
} from '@ant-design/icons-vue';
|
||||||
import { message } from 'ant-design-vue';
|
import { message } from 'ant-design-vue';
|
||||||
import AgentChatComponent from '@/components/AgentChatComponent.vue';
|
import AgentChatComponent from '@/components/AgentChatComponent.vue';
|
||||||
import TokenManagerComponent from '@/components/TokenManagerComponent.vue';
|
import TokenManagerComponent from '@/components/TokenManagerComponent.vue';
|
||||||
|
|
||||||
|
// 路由
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
// 状态
|
// 状态
|
||||||
const agents = ref({});
|
const agents = ref({});
|
||||||
const selectedAgentId = ref(null);
|
const selectedAgentId = ref(null);
|
||||||
@ -323,7 +342,7 @@ const fetchAgents = async () => {
|
|||||||
acc[agent.name] = agent;
|
acc[agent.name] = agent;
|
||||||
return acc;
|
return acc;
|
||||||
}, {});
|
}, {});
|
||||||
console.log("agents", agents.value);
|
// console.log("agents", agents.value);
|
||||||
|
|
||||||
// 加载当前选中智能体的配置
|
// 加载当前选中智能体的配置
|
||||||
if (selectedAgentId.value) {
|
if (selectedAgentId.value) {
|
||||||
@ -392,6 +411,13 @@ const getPlaceholder = (key, value) => {
|
|||||||
// 返回描述作为占位符
|
// 返回描述作为占位符
|
||||||
return `(默认: ${value.default})` ;
|
return `(默认: ${value.default})` ;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 跳转到独立智能体页面
|
||||||
|
const goToAgentPage = () => {
|
||||||
|
if (selectedAgentId.value) {
|
||||||
|
window.open(`/agent/${selectedAgentId.value}`, '_blank');
|
||||||
|
}
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
@ -531,6 +557,22 @@ const getPlaceholder = (key, value) => {
|
|||||||
.agent-info {
|
.agent-info {
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
min-width: calc(var(--agent-sidebar-width) - 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 {
|
.agent-name {
|
||||||
@ -623,6 +665,30 @@ const getPlaceholder = (key, value) => {
|
|||||||
gap: 10px;
|
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>
|
</style>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user