579 lines
24 KiB
TypeScript
579 lines
24 KiB
TypeScript
import React, { useState } from 'react';
|
||
import {
|
||
Search,
|
||
History,
|
||
Bot,
|
||
Sparkles,
|
||
Database,
|
||
Layers,
|
||
FileText,
|
||
ChevronRight,
|
||
ChevronLeft,
|
||
Cpu,
|
||
Target,
|
||
Zap,
|
||
CheckCircle,
|
||
} from 'lucide-react';
|
||
import { useTheme } from '../../contexts/ThemeContext';
|
||
import { PageType } from '../../components/Sidebar';
|
||
import { ChatMessage, EmptyChatState, QAComposer, TypingIndicator } from './QACommon';
|
||
|
||
interface Agent {
|
||
id: string;
|
||
name: string;
|
||
category: string;
|
||
tags: string[];
|
||
description: string;
|
||
skills: string[];
|
||
dataSources: string[];
|
||
functions: string[];
|
||
outputFields: string[];
|
||
}
|
||
|
||
interface Message {
|
||
id: string;
|
||
role: 'user' | 'assistant';
|
||
content: string;
|
||
timestamp: Date;
|
||
agentName?: string;
|
||
skills?: string[];
|
||
dataSources?: string[];
|
||
functions?: string[];
|
||
structuredOutput?: Record<string, any>;
|
||
}
|
||
|
||
/**
|
||
* 智能体问答组件
|
||
* 基于特定智能体的专业能力进行问答,支持选择不同领域的智能体
|
||
* @param onNavigate - 页面导航函数
|
||
*/
|
||
const AgentQA: React.FC<{ onNavigate: (page: PageType) => void }> = ({ onNavigate }) => {
|
||
const { theme } = useTheme();
|
||
const isDark = theme === 'dark';
|
||
|
||
// 模拟智能体列表
|
||
const agents: Agent[] = [
|
||
{
|
||
id: 'audience-agent',
|
||
name: 'AudienceAgent',
|
||
category: '受众分析',
|
||
tags: ['受众分层', '画像抽取', '行为预测'],
|
||
description: '专业的受众分析智能体,能够识别目标受众特征并生成画像',
|
||
skills: ['受众分层', '核心受众识别', '画像抽取', '行为预测'],
|
||
dataSources: ['知识库', 'Y系统', 'A系统'],
|
||
functions: ['信息抽取器', '标签聚类器', '结构化输出器'],
|
||
outputFields: ['core_audience', 'key_traits', 'barriers', 'opportunities'],
|
||
},
|
||
{
|
||
id: 'brand-agent',
|
||
name: 'BrandAgent',
|
||
category: '品牌分析',
|
||
tags: ['品牌定位', '传播策略', '调性分析'],
|
||
description: '专注品牌建设与传播策略的智能体',
|
||
skills: ['品牌定位分析', '传播路径规划', '品牌调性设计'],
|
||
dataSources: ['知识库', '行业数据库'],
|
||
functions: ['品牌诊断器', '策略生成器'],
|
||
outputFields: ['brand_position', 'communication_path', 'tone_guide'],
|
||
},
|
||
{
|
||
id: 'content-agent',
|
||
name: 'ContentAgent',
|
||
category: '内容创作',
|
||
tags: ['文案撰写', '创意生成', '多形式内容'],
|
||
description: '智能内容创作助手,支持多种形式的内容生成',
|
||
skills: ['文案撰写', '创意生成', '多形式内容', 'A/B测试文案'],
|
||
dataSources: ['知识库', '优秀案例库'],
|
||
functions: ['文案生成器', '风格适配器', '质量评估器'],
|
||
outputFields: ['headlines', 'body_copy', 'call_to_action', 'variants'],
|
||
},
|
||
{
|
||
id: 'channel-agent',
|
||
name: 'ChannelAgent',
|
||
category: '渠道规划',
|
||
tags: ['渠道选择', '投放策略', '效果评估'],
|
||
description: '专业的渠道分析与规划智能体',
|
||
skills: ['渠道选择', '投放策略规划', '效果评估', '预算分配'],
|
||
dataSources: ['Y系统', 'A系统', '行业数据'],
|
||
functions: ['渠道分析器', '投放优化器', 'ROI预测器'],
|
||
outputFields: ['recommended_channels', 'budget_allocation', 'expected_roi'],
|
||
},
|
||
];
|
||
|
||
// 状态管理
|
||
// 当前选中的智能体
|
||
const [selectedAgent, setSelectedAgent] = useState<Agent>(agents[0]);
|
||
// 智能体搜索关键词
|
||
const [searchQuery, setSearchQuery] = useState('');
|
||
// 聊天消息列表
|
||
const [messages, setMessages] = useState<Message[]>([]);
|
||
// 输入框内容
|
||
const [inputValue, setInputValue] = useState('');
|
||
// 加载状态
|
||
const [isLoading, setIsLoading] = useState(false);
|
||
// 左侧侧边栏折叠状态
|
||
const [isLeftSidebarCollapsed, setIsLeftSidebarCollapsed] = useState(false);
|
||
|
||
// 过滤智能体
|
||
const filteredAgents = agents.filter(agent =>
|
||
agent.name.toLowerCase().includes(searchQuery.toLowerCase()) ||
|
||
agent.category.toLowerCase().includes(searchQuery.toLowerCase()) ||
|
||
agent.tags.some(tag => tag.toLowerCase().includes(searchQuery.toLowerCase()))
|
||
);
|
||
|
||
/**
|
||
* 处理发送消息
|
||
* 发送用户消息并模拟智能体响应
|
||
*/
|
||
const handleSend = () => {
|
||
if (!inputValue.trim()) return;
|
||
|
||
setIsLoading(true);
|
||
|
||
const userMessage: Message = {
|
||
id: Date.now().toString(),
|
||
role: 'user',
|
||
content: inputValue,
|
||
timestamp: new Date(),
|
||
};
|
||
|
||
setMessages([...messages, userMessage]);
|
||
setInputValue('');
|
||
|
||
// 模拟AI响应
|
||
setTimeout(() => {
|
||
const response: Message = {
|
||
id: (Date.now() + 1).toString(),
|
||
role: 'assistant',
|
||
content: `基于${selectedAgent.name}的专业能力,我来为您分析:\n\n根据您的问题,我识别到核心受众特征如下:\n\n**核心受众识别**:\n- 主要年龄段:25-35岁\n- 职业特征:都市白领\n- 消费能力:中高端\n- 关注点:品质生活、个人成长\n\n**关键特质**:\n1. 追求个性化表达\n2. 注重社交认同\n3. 愿意为品质付费\n\n**可能存在的阻力**:\n- 价格敏感度较高\n- 对品牌忠诚度有限\n\n以上分析是否满足您的需求?如需调整维度,请继续补充信息。`,
|
||
timestamp: new Date(),
|
||
agentName: selectedAgent.name,
|
||
skills: selectedAgent.skills,
|
||
dataSources: selectedAgent.dataSources,
|
||
functions: selectedAgent.functions,
|
||
structuredOutput: {
|
||
core_audience: '25-35岁都市白领',
|
||
key_traits: ['追求个性化', '注重社交认同', '品质导向'],
|
||
barriers: ['价格敏感', '品牌忠诚度有限'],
|
||
opportunities: ['社交媒体影响大', '口碑传播效果好'],
|
||
},
|
||
};
|
||
|
||
setMessages(prev => [...prev, response]);
|
||
setIsLoading(false);
|
||
}, 1500);
|
||
};
|
||
|
||
/**
|
||
* 处理停止操作
|
||
* 停止当前正在进行的智能体响应
|
||
*/
|
||
const handleStop = () => {
|
||
setIsLoading(false);
|
||
};
|
||
|
||
/**
|
||
* 处理键盘事件
|
||
* 按Enter键发送消息(不按Shift)
|
||
*/
|
||
const handleKeyDown = (e: React.KeyboardEvent) => {
|
||
if (e.key === 'Enter' && !e.shiftKey) {
|
||
e.preventDefault();
|
||
handleSend();
|
||
}
|
||
};
|
||
|
||
/**
|
||
* 保存问答记录
|
||
*/
|
||
const handleSaveRecord = () => {
|
||
alert('问答记录已保存');
|
||
};
|
||
|
||
/**
|
||
* 收藏当前对话
|
||
*/
|
||
const handleCollect = () => {
|
||
alert('已添加到收藏');
|
||
};
|
||
|
||
return (
|
||
<div className={`h-[calc(100vh-120px)] flex flex-col theme-bg rounded-xl ${isDark ? 'bg-slate-800/50' : 'bg-white'} border ${isDark ? 'border-slate-700/50' : 'border-red-100'}`}>
|
||
{/* 顶部工具栏 */}
|
||
<div className={`flex items-center justify-between px-6 py-4 border-b ${isDark ? 'border-slate-700/50' : 'border-red-100'}`}>
|
||
<div className="flex items-center gap-4">
|
||
<h1 className={`text-lg font-semibold ${isDark ? 'text-white' : 'text-gray-900'}`}>
|
||
智能体问答
|
||
</h1>
|
||
<div className={`flex items-center gap-2 px-3 py-1.5 rounded-lg ${isDark ? 'bg-slate-700/50' : 'bg-red-50'}`}>
|
||
<Bot className={`w-4 h-4 ${isDark ? 'text-blue-400' : 'text-red-500'}`} />
|
||
<span className={`text-sm ${isDark ? 'text-slate-300' : 'text-gray-700'}`}>
|
||
当前智能体:
|
||
</span>
|
||
<span className={`text-sm font-medium ${isDark ? 'text-blue-400' : 'text-red-600'}`}>
|
||
{selectedAgent.name}
|
||
</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="flex items-center gap-2">
|
||
<button
|
||
onClick={() => onNavigate('qa-records')}
|
||
className={`flex items-center gap-2 px-4 py-2 rounded-lg text-sm font-medium transition-all ${
|
||
isDark
|
||
? 'bg-slate-700/50 text-slate-300 hover:bg-slate-600/50'
|
||
: 'bg-gray-100 text-gray-700 hover:bg-gray-200'
|
||
}`}
|
||
>
|
||
<History className="w-4 h-4" />
|
||
历史记录
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
{/* 主体内容区 */}
|
||
<div className="flex-1 flex overflow-hidden">
|
||
{/* 左侧智能体区 */}
|
||
<div className={`${isLeftSidebarCollapsed ? 'w-14 p-2' : 'w-72'} border-r flex-shrink-0 overflow-y-auto transition-all duration-300 ${isDark ? 'border-slate-700/50 bg-slate-800/30' : 'border-red-100 bg-gray-50/50'}`}>
|
||
<div className={`flex items-center ${isLeftSidebarCollapsed ? 'justify-center' : 'justify-between'} p-2 ${isLeftSidebarCollapsed ? '' : 'px-4 pt-4 pb-0'}`}>
|
||
{!isLeftSidebarCollapsed && (
|
||
<span className={`text-xs font-medium uppercase tracking-wider ${isDark ? 'text-slate-500' : 'text-gray-400'}`}>
|
||
智能体配置
|
||
</span>
|
||
)}
|
||
<button
|
||
type="button"
|
||
onClick={() => setIsLeftSidebarCollapsed(!isLeftSidebarCollapsed)}
|
||
className={`p-2 rounded-lg transition-all ${
|
||
isDark
|
||
? 'text-slate-400 hover:text-white hover:bg-slate-700/50'
|
||
: 'text-gray-500 hover:text-red-600 hover:bg-red-50'
|
||
}`}
|
||
title={isLeftSidebarCollapsed ? '展开侧边栏' : '收起侧边栏'}
|
||
>
|
||
{isLeftSidebarCollapsed ? <ChevronRight className="w-4 h-4" /> : <ChevronLeft className="w-4 h-4" />}
|
||
</button>
|
||
</div>
|
||
|
||
{!isLeftSidebarCollapsed && (<>
|
||
{/* 智能体搜索 */}
|
||
<div className="p-4">
|
||
<div className={`relative ${isDark ? 'bg-slate-700/50' : 'bg-white'} rounded-lg`}>
|
||
<Search className={`absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 ${isDark ? 'text-slate-400' : 'text-gray-400'}`} />
|
||
<input
|
||
type="text"
|
||
value={searchQuery}
|
||
onChange={(e) => setSearchQuery(e.target.value)}
|
||
placeholder="搜索智能体..."
|
||
className={`w-full pl-10 pr-4 py-2 rounded-lg text-sm focus:outline-none ${
|
||
isDark
|
||
? 'bg-transparent text-white placeholder-slate-500'
|
||
: 'bg-transparent text-gray-800 placeholder-gray-400'
|
||
}`}
|
||
/>
|
||
</div>
|
||
</div>
|
||
|
||
{/* 智能体列表 */}
|
||
<div className="px-4 pb-4">
|
||
<h3 className={`text-xs font-medium uppercase tracking-wider mb-3 ${isDark ? 'text-slate-500' : 'text-gray-400'}`}>
|
||
智能体列表
|
||
</h3>
|
||
<div className="space-y-2">
|
||
{filteredAgents.map((agent) => (
|
||
<button
|
||
key={agent.id}
|
||
onClick={() => setSelectedAgent(agent)}
|
||
className={`w-full text-left p-3 rounded-lg transition-all ${
|
||
selectedAgent.id === agent.id
|
||
? isDark
|
||
? 'bg-blue-600/20 border border-blue-500/50'
|
||
: 'bg-red-50 border border-red-200'
|
||
: isDark
|
||
? 'bg-slate-700/30 border border-transparent hover:bg-slate-700/50'
|
||
: 'bg-white border border-gray-200 hover:bg-gray-50'
|
||
}`}
|
||
>
|
||
<div className="flex items-center gap-3">
|
||
<div className={`w-10 h-10 rounded-lg flex items-center justify-center ${
|
||
selectedAgent.id === agent.id
|
||
? isDark
|
||
? 'bg-blue-600 text-white'
|
||
: 'bg-red-500 text-white'
|
||
: isDark
|
||
? 'bg-slate-600 text-slate-300'
|
||
: 'bg-gray-100 text-gray-600'
|
||
}`}>
|
||
<Bot className="w-5 h-5" />
|
||
</div>
|
||
<div className="flex-1 min-w-0">
|
||
<div className={`text-sm font-medium truncate ${isDark ? 'text-white' : 'text-gray-900'}`}>
|
||
{agent.name}
|
||
</div>
|
||
<div className={`text-xs ${isDark ? 'text-slate-400' : 'text-gray-500'}`}>
|
||
{agent.category}
|
||
</div>
|
||
</div>
|
||
<ChevronRight className={`w-4 h-4 ${isDark ? 'text-slate-500' : 'text-gray-400'}`} />
|
||
</div>
|
||
</button>
|
||
))}
|
||
</div>
|
||
</div>
|
||
|
||
{/* 当前智能体能力摘要 */}
|
||
<div className={`p-4 border-t ${isDark ? 'border-slate-700/50' : 'border-red-100'}`}>
|
||
<h3 className={`text-xs font-medium uppercase tracking-wider mb-3 ${isDark ? 'text-slate-500' : 'text-gray-400'}`}>
|
||
能力摘要
|
||
</h3>
|
||
|
||
{/* 核心职责 */}
|
||
<div className="mb-4">
|
||
<div className={`flex items-center gap-2 mb-2 ${isDark ? 'text-slate-400' : 'text-gray-500'}`}>
|
||
<Target className="w-4 h-4" />
|
||
<span className="text-xs">核心职责</span>
|
||
</div>
|
||
<p className={`text-sm ${isDark ? 'text-slate-300' : 'text-gray-700'}`}>
|
||
{selectedAgent.description}
|
||
</p>
|
||
</div>
|
||
|
||
{/* 已启用技能 */}
|
||
<div className="mb-4">
|
||
<div className={`flex items-center gap-2 mb-2 ${isDark ? 'text-slate-400' : 'text-gray-500'}`}>
|
||
<Sparkles className="w-4 h-4" />
|
||
<span className="text-xs">已启用技能</span>
|
||
</div>
|
||
<div className="flex flex-wrap gap-1">
|
||
{selectedAgent.skills.map((skill, idx) => (
|
||
<span
|
||
key={idx}
|
||
className={`px-2 py-0.5 rounded text-xs ${
|
||
isDark ? 'bg-blue-600/30 text-blue-400' : 'bg-blue-100 text-blue-600'
|
||
}`}
|
||
>
|
||
{skill}
|
||
</span>
|
||
))}
|
||
</div>
|
||
</div>
|
||
|
||
{/* 可访问数据源 */}
|
||
<div className="mb-4">
|
||
<div className={`flex items-center gap-2 mb-2 ${isDark ? 'text-slate-400' : 'text-gray-500'}`}>
|
||
<Database className="w-4 h-4" />
|
||
<span className="text-xs">可访问数据源</span>
|
||
</div>
|
||
<div className="flex flex-wrap gap-1">
|
||
{selectedAgent.dataSources.map((source, idx) => (
|
||
<span
|
||
key={idx}
|
||
className={`px-2 py-0.5 rounded text-xs ${
|
||
isDark ? 'bg-green-600/30 text-green-400' : 'bg-green-100 text-green-600'
|
||
}`}
|
||
>
|
||
{source}
|
||
</span>
|
||
))}
|
||
</div>
|
||
</div>
|
||
|
||
{/* 可调用功能 */}
|
||
<div>
|
||
<div className={`flex items-center gap-2 mb-2 ${isDark ? 'text-slate-400' : 'text-gray-500'}`}>
|
||
<Layers className="w-4 h-4" />
|
||
<span className="text-xs">可调用功能</span>
|
||
</div>
|
||
<div className="flex flex-wrap gap-1">
|
||
{selectedAgent.functions.map((func, idx) => (
|
||
<span
|
||
key={idx}
|
||
className={`px-2 py-0.5 rounded text-xs ${
|
||
isDark ? 'bg-purple-600/30 text-purple-400' : 'bg-purple-100 text-purple-600'
|
||
}`}
|
||
>
|
||
{func}
|
||
</span>
|
||
))}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</>)}
|
||
</div>
|
||
|
||
{/* 中间对话区 */}
|
||
<div className="flex-1 flex flex-col overflow-hidden">
|
||
{/* 消息列表 */}
|
||
<div className="flex-1 overflow-y-auto p-4 space-y-4">
|
||
{messages.length === 0 ? (
|
||
<EmptyChatState
|
||
icon={<Bot className="w-11 h-11 opacity-60" />}
|
||
title={`开始与${selectedAgent.name}对话`}
|
||
description="基于智能体专业能力获取精准回答"
|
||
/>
|
||
) : (
|
||
messages.map((msg) => (
|
||
<ChatMessage
|
||
key={msg.id}
|
||
message={msg}
|
||
assistantLabel={msg.agentName || selectedAgent.name}
|
||
renderAssistantExtra={(assistantMessage) => (
|
||
<div className={`ml-12 p-3 rounded-xl ${isDark ? 'bg-slate-800/50' : 'bg-gray-50'}`}>
|
||
<div className="mb-3">
|
||
<h4 className={`text-xs font-medium mb-2 ${isDark ? 'text-slate-400' : 'text-gray-500'}`}>本轮启用技能</h4>
|
||
<div className="flex flex-wrap gap-1">
|
||
{assistantMessage.skills?.map((skill, idx) => (
|
||
<span key={idx} className={`px-2 py-0.5 rounded text-xs ${isDark ? 'bg-blue-600/30 text-blue-400' : 'bg-blue-100 text-blue-600'}`}>
|
||
{skill}
|
||
</span>
|
||
))}
|
||
</div>
|
||
</div>
|
||
|
||
<div className="mb-3">
|
||
<h4 className={`text-xs font-medium mb-2 ${isDark ? 'text-slate-400' : 'text-gray-500'}`}>本轮访问数据源</h4>
|
||
<div className="flex flex-wrap gap-1">
|
||
{assistantMessage.dataSources?.map((source, idx) => (
|
||
<span key={idx} className={`px-2 py-0.5 rounded text-xs ${isDark ? 'bg-green-600/30 text-green-400' : 'bg-green-100 text-green-600'}`}>
|
||
{source}
|
||
</span>
|
||
))}
|
||
</div>
|
||
</div>
|
||
|
||
<div className="mb-3">
|
||
<h4 className={`text-xs font-medium mb-2 ${isDark ? 'text-slate-400' : 'text-gray-500'}`}>本轮调用功能</h4>
|
||
<div className="flex flex-wrap gap-1">
|
||
{assistantMessage.functions?.map((func, idx) => (
|
||
<span key={idx} className={`px-2 py-0.5 rounded text-xs ${isDark ? 'bg-purple-600/30 text-purple-400' : 'bg-purple-100 text-purple-600'}`}>
|
||
{func}
|
||
</span>
|
||
))}
|
||
</div>
|
||
</div>
|
||
|
||
{assistantMessage.structuredOutput && (
|
||
<div>
|
||
<h4 className={`text-xs font-medium mb-2 ${isDark ? 'text-slate-400' : 'text-gray-500'}`}>结构化输出</h4>
|
||
<div className={`p-3 rounded-lg ${isDark ? 'bg-slate-700/50' : 'bg-white'}`}>
|
||
{Object.entries(assistantMessage.structuredOutput).map(([key, value]) => (
|
||
<div key={key} className="flex items-start gap-2 mb-1 last:mb-0">
|
||
<span className={`text-xs font-mono ${isDark ? 'text-blue-400' : 'text-blue-600'}`}>{key}:</span>
|
||
<span className={`text-xs ${isDark ? 'text-slate-300' : 'text-gray-600'}`}>
|
||
{Array.isArray(value) ? value.join(', ') : String(value)}
|
||
</span>
|
||
</div>
|
||
))}
|
||
</div>
|
||
</div>
|
||
)}
|
||
</div>
|
||
)}
|
||
/>
|
||
))
|
||
)}
|
||
|
||
{isLoading && <TypingIndicator label={`${selectedAgent.name} 正在调用能力生成回复`} assistantLabel={selectedAgent.name} />}
|
||
</div>
|
||
|
||
{/* 底部输入区 */}
|
||
<QAComposer
|
||
value={inputValue}
|
||
onChange={setInputValue}
|
||
onKeyDown={handleKeyDown}
|
||
onSubmit={handleSend}
|
||
onStop={handleStop}
|
||
onSave={handleSaveRecord}
|
||
onCollect={handleCollect}
|
||
isLoading={isLoading}
|
||
placeholder="输入问题或任务要求..."
|
||
showUpload={false}
|
||
/>
|
||
</div>
|
||
|
||
{/* 右侧执行详情区 */}
|
||
<div className={`w-72 border-l flex-shrink-0 overflow-y-auto p-4 ${
|
||
isDark ? 'border-slate-700/50 bg-slate-800/30' : 'border-red-100 bg-gray-50/50'
|
||
}`}>
|
||
<h3 className={`text-sm font-medium mb-4 ${isDark ? 'text-slate-300' : 'text-gray-700'}`}>
|
||
执行详情
|
||
</h3>
|
||
|
||
{/* 本轮启用技能 */}
|
||
<div className="mb-6">
|
||
<div className={`flex items-center gap-2 mb-3 ${isDark ? 'text-slate-400' : 'text-gray-500'}`}>
|
||
<Sparkles className="w-4 h-4" />
|
||
<span className="text-xs font-medium">本轮启用技能</span>
|
||
</div>
|
||
<div className={`p-3 rounded-xl ${isDark ? 'bg-slate-700/50' : 'bg-white'}`}>
|
||
<div className="space-y-2">
|
||
{selectedAgent.skills.map((skill, idx) => (
|
||
<div key={idx} className="flex items-center gap-2">
|
||
<CheckCircle className={`w-3 h-3 ${isDark ? 'text-blue-400' : 'text-green-500'}`} />
|
||
<span className={`text-sm ${isDark ? 'text-slate-300' : 'text-gray-600'}`}>{skill}</span>
|
||
</div>
|
||
))}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{/* 本轮访问数据源 */}
|
||
<div className="mb-6">
|
||
<div className={`flex items-center gap-2 mb-3 ${isDark ? 'text-slate-400' : 'text-gray-500'}`}>
|
||
<Database className="w-4 h-4" />
|
||
<span className="text-xs font-medium">本轮访问数据源</span>
|
||
</div>
|
||
<div className={`p-3 rounded-xl ${isDark ? 'bg-slate-700/50' : 'bg-white'}`}>
|
||
<div className="space-y-2">
|
||
{selectedAgent.dataSources.map((source, idx) => (
|
||
<div key={idx} className="flex items-center gap-2">
|
||
<Database className={`w-3 h-3 ${isDark ? 'text-green-400' : 'text-green-500'}`} />
|
||
<span className={`text-sm ${isDark ? 'text-slate-300' : 'text-gray-600'}`}>{source}</span>
|
||
</div>
|
||
))}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{/* 本轮调用功能 */}
|
||
<div className="mb-6">
|
||
<div className={`flex items-center gap-2 mb-3 ${isDark ? 'text-slate-400' : 'text-gray-500'}`}>
|
||
<Layers className="w-4 h-4" />
|
||
<span className="text-xs font-medium">本轮调用功能</span>
|
||
</div>
|
||
<div className={`p-3 rounded-xl ${isDark ? 'bg-slate-700/50' : 'bg-white'}`}>
|
||
<div className="space-y-2">
|
||
{selectedAgent.functions.map((func, idx) => (
|
||
<div key={idx} className="flex items-center gap-2">
|
||
<Cpu className={`w-3 h-3 ${isDark ? 'text-purple-400' : 'text-purple-500'}`} />
|
||
<span className={`text-sm ${isDark ? 'text-slate-300' : 'text-gray-600'}`}>{func}</span>
|
||
</div>
|
||
))}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{/* 结构化输出字段 */}
|
||
<div>
|
||
<div className={`flex items-center gap-2 mb-3 ${isDark ? 'text-slate-400' : 'text-gray-500'}`}>
|
||
<FileText className="w-4 h-4" />
|
||
<span className="text-xs font-medium">输出字段</span>
|
||
</div>
|
||
<div className={`p-3 rounded-xl ${isDark ? 'bg-slate-700/50' : 'bg-white'}`}>
|
||
<div className="space-y-2">
|
||
{selectedAgent.outputFields.map((field, idx) => (
|
||
<div key={idx} className="flex items-center gap-2">
|
||
<Zap className={`w-3 h-3 ${isDark ? 'text-yellow-400' : 'text-yellow-500'}`} />
|
||
<span className={`text-xs font-mono ${isDark ? 'text-blue-400' : 'text-blue-600'}`}>{field}</span>
|
||
</div>
|
||
))}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
);
|
||
};
|
||
|
||
export default AgentQA;
|