Files
ailine/frontend/FRONTEND_GUIDE.md
root 7a769fab14
Some checks failed
构建并部署 AI Agent 服务 / deploy (push) Failing after 6m9s
feat: 完善 SSE 事件类型,添加完整 React 组件支持思考过程、工具调用、人工审核
2026-04-26 16:05:44 +08:00

8.6 KiB
Raw Blame History

AI Agent 前端展示 - 完整实现文档

一、概述

本文档描述了 AI Agent 对话系统的前端展示实现,包括:

  • 思考过程展示
  • 工具调用与结果展示
  • 最终回答流式渲染
  • 人工介入确认显示

二、后端 SSE 事件类型

事件类型汇总

事件类型 说明 数据结构
node_start 节点开始执行 { type: "node_start", node: string }
node_end 节点执行结束 { type: "node_end", node: string }
reasoning 思考过程 token { type: "reasoning", node: string, content: string }
tool_call_start 工具调用开始 { type: "tool_call_start", tool: string, args: any, id: string }
tool_call_end 工具调用结束 { type: "tool_call_end", tool: string, id: string, result: string }
llm_token 最终回答 token { type: "llm_token", node: string, content: string }
human_review_request 人工审核请求 { type: "human_review_request", review_id: string, content: string }
state_update 状态更新 { type: "state_update", data: any }
custom 自定义事件 { type: "custom", data: any }
done 对话完成 { type: "done" }

事件处理流程

用户消息
  ↓
[node_start] llm_call
  ↓
[reasoning] 思考过程流式输出
  ↓
[tool_call_start] 工具调用开始
  ↓
[node_end] llm_call
  ↓
[node_start] tool_node
  ↓
[tool_call_end] 工具调用完成,返回结果
  ↓
[node_end] tool_node
  ↓
[node_start] llm_call
  ↓
[llm_token] 最终回答流式输出
  ↓
[node_end] llm_call
  ↓
[human_review_request] 人工审核请求(如有)
  ↓
[done]

三、前端组件结构

组件树

ChatContainer (主容器)
├── useChat (自定义 Hook)
│   ├── ApiClient (API 客户端)
│   └── 状态管理
├── UserMessage (用户消息)
└── AssistantMessage (AI 消息)
    ├── ReasoningSection (思考过程)
    ├── ToolCallCard[] (工具调用卡片)
    ├── HumanReviewCard (人工审核卡片)
    └── 最终回答内容

四、视觉设计规范

1. 思考区Reasoning Section

// 设计规范
{
  icon: '💭',
  style: {
    background: 'bg-gray-50',
    border: 'border-gray-200',
    text: 'text-gray-600 italic',
  },
  interaction: {
    collapsible: true,
    streaming: true,
  }
}

2. 工具调用区Tool Call Card

// 设计规范
{
  icon: '⚙️',
  statusIcons: {
    pending: '⏳',
    running: '🔄',
    success: '✅',
    error: '❌',
  },
  colors: {
    pending: 'border-gray-300 bg-gray-50',
    running: 'border-blue-300 bg-blue-50',
    success: 'border-green-300 bg-green-50',
    error: 'border-red-300 bg-red-50',
  },
  features: {
    argsCollapsible: true,
    resultCollapsible: true,
  }
}

3. 最终回答区Final Answer

// 设计规范
{
  style: {
    background: 'bg-blue-50',
    border: 'border-blue-100',
  },
  interaction: {
    streaming: true,
    cursorBlink: true,
  },
  actions: {
    copy: true,
    feedback: true,
  }
}

4. 人工审核区Human Review Card

// 设计规范
{
  icon: '👤',
  style: {
    background: 'bg-yellow-50',
    border: 'border-yellow-300',
  },
  actions: {
    approve: true,
    reject: true,
    modify: true,
  },
  fields: {
    contentToReview: true,
    comment: true,
    modifiedContent: true,
  }
}

五、使用示例

基本使用

import React from 'react';
import ChatContainer from './components/ChatContainer';

function App() {
  return (
    <div className="app">
      <ChatContainer 
        model="zhipu" 
        threadId="my-thread-123"
      />
    </div>
  );
}

export default App;

自定义 API 客户端

import { ApiClient } from './components/useChat';

const customClient = new ApiClient('http://my-custom-backend:8080');

// 流式对话
async function streamChat() {
  for await (const event of customClient.chatStream(
    '你好',
    'thread-1',
    'zhipu'
  )) {
    console.log('Event:', event);
  }
}

// 审核操作
await customClient.approveReview('review-123', 'user@example.com', '内容正确');
await customClient.rejectReview('review-123', 'user@example.com', '内容有误');
await customClient.modifyReview(
  'review-123',
  'user@example.com',
  '修改后的内容',
  '调整了措辞'
);

自定义样式

import { AssistantMessage } from './components/ChatContainer';

// 自定义组件
const CustomAssistantMessage = ({ message }) => (
  <div className="my-custom-style">
    {/* 自定义思考区 */}
    <MyCustomReasoning content={message.reasoning} />
    
    {/* 自定义工具卡片 */}
    {message.toolCalls.map(tc => (
      <MyCustomToolCall key={tc.id} toolCall={tc} />
    ))}
    
    {/* 自定义审核卡片 */}
    {message.humanReview && (
      <MyCustomReview review={message.humanReview} />
    )}
    
    {/* 自定义回答 */}
    <div className="my-answer">{message.content}</div>
  </div>
);

六、后端修改说明

修改的文件

  1. backend/app/agent/service.py - 补充完整 SSE 事件类型

新增的事件处理逻辑

# 节点开始/结束事件
if node_name != current_node:
    if current_node:
        yield { "type": "node_end", "node": current_node }
    yield { "type": "node_start", "node": node_name }
    current_node = node_name

# 思考过程事件
if reasoning_token:
    yield { "type": "reasoning", "node": node_name, "content": reasoning_token }

# 工具调用开始事件
if tool_call_id not in tool_calls_in_progress:
    yield {
        "type": "tool_call_start",
        "tool": tool_name,
        "args": tool_args,
        "id": tool_call_id
    }

# 工具调用结束事件
if msg.get("role") == "tool":
    yield {
        "type": "tool_call_end",
        "tool": tool_name,
        "id": tool_call_id,
        "result": tool_output
    }

# 人工审核请求事件
if "review_pending" in serialized_data and serialized_data["review_pending"]:
    yield {
        "type": "human_review_request",
        "review_id": review_id,
        "content": content_to_review
    }

七、状态管理

Message 接口

interface Message {
  id: string;
  role: 'user' | 'assistant';
  content: string;
  reasoning: string;
  toolCalls: ToolCall[];
  humanReview?: HumanReview;
  isLoading: boolean;
  timestamp: Date;
}

ToolCall 接口

interface ToolCall {
  id: string;
  tool: string;
  args: any;
  status: 'pending' | 'running' | 'success' | 'error';
  result?: string;
}

HumanReview 接口

interface HumanReview {
  reviewId: string;
  content: string;
  status: 'pending' | 'approved' | 'rejected' | 'modified';
  comment?: string;
  modifiedContent?: string;
}

八、文件清单

后端文件

文件 说明
backend/app/agent/service.py 补充完整 SSE 事件类型
backend/app/agent_subgraphs/common/human_review.py 人工审核功能(已有)

前端文件

文件 说明
frontend/src/components/useChat.ts 自定义 Hook + API 客户端
frontend/src/components/ChatContainer.tsx 完整 UI 组件

文档文件

文件 说明
backend/docs/RAG_EVALUATION_GUIDE.md RAG 评估指南
frontend/FRONTEND_GUIDE.md 本文档

九、测试方法

测试用例 1简单对话

输入:

你好,请介绍一下你自己

预期输出:

[思考过程] 我需要介绍自己...
[最终回答] 你好!我是 AI Agent...

测试用例 2工具调用

输入:

请帮我查询北京的天气

预期输出:

[思考过程] 用户要查询天气...
[tool_call_start] get_weather { city: "北京" }
[tool_call_end] 结果: "北京, 晴天, 25°C"
[最终回答] 北京今天天气是晴,气温 25°C...

测试用例 3人工审核

输入:

请生成一份重要邮件内容

预期输出:

[思考过程] 用户要生成邮件...
[最终回答] 邮件内容...
[human_review_request] 需要审核...
[审核卡片] 通过 / 拒绝 / 修改

十、常见问题

Q: 如何自定义样式?

A: 复制组件文件,修改 className 或样式对象即可。

Q: 如何添加新的事件类型?

A: 1. 在后端添加 yield 语句2. 在前端 useChat 中添加 case 分支3. 在 UI 中添加展示组件。

Q: 如何处理多个工具调用?

A: ToolCallCard 组件支持数组,每个工具调用独立显示。

Q: 如何集成现有项目?

A: 1. 复制后端修改2. 复制前端组件3. 根据项目调整 API 端点。