feat(ai): 重构AI聊天模块,使用agno框架替代langchain

- 移除langchain相关依赖,引入agno作为大模型开发框架
- 重构聊天会话和消息存储,使用agno的TeamSession管理
- 合并chat_message和chat_session模块为统一的chat模块
- 更新前端API和类型定义,适配新的后端接口
- 优化数据库日志字段类型,根据数据库类型自动选择
- 重构AI助手组件,使用新的聊天API
- 清理不再使用的模型、控制器和服务代码
This commit is contained in:
zhangtao
2026-03-13 00:41:44 +08:00
parent 8b83caf7fc
commit e03692467b
40 changed files with 2251 additions and 2650 deletions
+58 -6
View File
@@ -119,11 +119,11 @@
</template>
<script setup lang="ts">
import { nextTick, onBeforeUnmount, onMounted, watch } from "vue";
import { nextTick, onBeforeUnmount, onMounted, watch, ref, computed } from "vue";
import { useRouter } from "vue-router";
import { ElMessage } from "element-plus";
import { useSettingsStore } from "@/store";
import McpAPI from "@/api/module_application/mcp";
import { AiChatAPI, ChatSession, ChatSessionDetail } from "@/api/module_ai/chat";
type ToolFunctionCall = {
name: string;
@@ -165,6 +165,12 @@ const command = ref("");
const loading = ref(false);
const response = ref<AiResponse | null>(null);
// 会话管理
const sessions = ref<ChatSession[]>([]);
const currentSessionId = ref<string | null>(null);
const currentSession = ref<ChatSessionDetail | null>(null);
const sessionLoading = ref(false);
const fabCollapsed = useStorage<boolean>("vea:ui:ai_assistant_fab_collapsed", false);
const fabRight = ref(30);
@@ -300,11 +306,46 @@ const examples = [
"获取姓名为张三的用户信息",
];
// 加载会话列表
const loadSessions = async () => {
try {
sessionLoading.value = true;
const response = await AiChatAPI.getSessionList({ page_no: 1, page_size: 100 });
if (response.data?.success) {
sessions.value = response.data.data?.items || [];
}
} catch (error) {
console.error("加载会话列表失败:", error);
} finally {
sessionLoading.value = false;
}
};
// 加载会话详情
const loadSessionDetail = async (sessionId: string) => {
try {
sessionLoading.value = true;
const response = await AiChatAPI.getSessionDetail(sessionId);
if (response.data?.success) {
currentSessionId.value = sessionId;
currentSession.value = response.data.data;
} else {
ElMessage.error("获取会话详情失败");
}
} catch (error) {
console.error("获取会话详情失败:", error);
ElMessage.error("获取会话详情失败");
} finally {
sessionLoading.value = false;
}
};
// 打开对话框
const handleOpen = () => {
dialogVisible.value = true;
command.value = "";
response.value = null;
loadSessions();
};
// 关闭对话框
@@ -334,8 +375,9 @@ const handleExecute = async () => {
try {
// 调用 AI API 解析命令
const result = await McpAPI.chatMcp({
const result = await AiChatAPI.chat({
message: rawCommand,
session_id: currentSessionId.value || undefined,
});
if (!result.data.success) {
@@ -343,10 +385,18 @@ const handleExecute = async () => {
return;
}
// 更新会话ID
if (result.data.data?.session_id) {
currentSessionId.value = result.data.data.session_id;
// 重新加载会话列表和详情
await loadSessions();
await loadSessionDetail(result.data.data.session_id);
}
// 解析 AI 返回的操作类型
const action = parseAction(result.data, rawCommand);
const action = parseAction(result.data.data, rawCommand);
response.value = {
explanation: result.data.msg ?? "命令解析成功,准备执行操作",
explanation: result.data.data?.response ?? "命令解析成功,准备执行操作",
action,
};
@@ -475,7 +525,9 @@ const tryDirectNavigate = (rawCommand: string): AiResponse | null => {
// 解析 AI 返回的操作类型
const parseAction = (result: any, rawCommand: string): AiAction | null => {
const cmd = normalizeText(rawCommand);
const primaryCall = result.functionCalls?.[0];
// 后端返回的是 function_calls(下划线命名)
const functionCalls = result.function_calls || result.functionCalls;
const primaryCall = functionCalls?.[0];
const functionName = primaryCall?.name;
// 优先从函数名推断路由,其次从命令文本匹配