change to next
This commit is contained in:
127
web/src/app/chat/index.tsx
Normal file
127
web/src/app/chat/index.tsx
Normal file
@@ -0,0 +1,127 @@
|
||||
import { app } from '@/agent/index.ts'
|
||||
import { useStudioStore } from '../studio/store';
|
||||
import { useShallow } from 'zustand/shallow';
|
||||
import { useState } from 'react';
|
||||
import { query } from '@/modules/query.ts'
|
||||
import { QueryViewMessages } from '../query-view';
|
||||
import { toast } from 'react-toastify';
|
||||
export const Chat = () => {
|
||||
const studioStore = useStudioStore(useShallow((state) => ({
|
||||
routes: state.routes,
|
||||
showRightPanel: state.showRightPanel,
|
||||
setShowRightPanel: state.setShowRightPanel,
|
||||
addMessage: state.addMessage,
|
||||
})));
|
||||
const [text, setText] = useState('');
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const onSend = async () => {
|
||||
if (!text.trim() || isLoading) return;
|
||||
setIsLoading(true);
|
||||
const { routes } = studioStore;
|
||||
let callPrompts = '';
|
||||
const toolsList = routes.map((r, index) =>
|
||||
`${index + 1}. 工具名称: ${r.id}\n 描述: ${r.description}`
|
||||
).join('\n\n');
|
||||
|
||||
callPrompts = `你是一个 AI 助手,你可以使用以下工具来帮助用户完成任务:
|
||||
|
||||
${toolsList}
|
||||
|
||||
## 回复规则
|
||||
1. 如果用户的请求可以使用上述工具完成,请返回 JSON 格式数据
|
||||
2. 如果没有合适的工具,请直接分析并回答用户问题
|
||||
|
||||
## JSON 数据格式
|
||||
\`\`\`json
|
||||
{
|
||||
"id": "工具的id",
|
||||
"payload": {
|
||||
// 工具所需的参数(如果需要)
|
||||
// 例如: "id": "xxx", "name": "xxx"
|
||||
}
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
注意:
|
||||
- payload 中包含工具执行所需的所有参数
|
||||
- 如果工具不需要参数,payload 可以为空对象 {}
|
||||
- 确保返回的 id 与上述工具列表中的工具名称完全匹配`
|
||||
|
||||
const res = await query.post({
|
||||
path: 'ai',
|
||||
payload: {
|
||||
messages: [
|
||||
{
|
||||
role: 'system',
|
||||
content: callPrompts
|
||||
},
|
||||
{
|
||||
role: 'user',
|
||||
content: text
|
||||
}
|
||||
],
|
||||
isJson: true
|
||||
}
|
||||
})
|
||||
setText('');
|
||||
console.log('发送消息', text, res);
|
||||
if (res.code === 200) {
|
||||
// 处理返回结果
|
||||
const payload = res.data?.action;
|
||||
if (payload) {
|
||||
const route = routes.find(r => r.id === payload.id);
|
||||
const { path, key } = route || {};
|
||||
const { id, ...otherParams } = payload.payload || {};
|
||||
const action = { path, key, ...otherParams }
|
||||
let response;
|
||||
if (route) {
|
||||
response = await app.run(action);
|
||||
// toast.success('工具调用成功');
|
||||
} else {
|
||||
console.error('未找到对应工具', payload.id);
|
||||
toast.error('未找到对应工具');
|
||||
return
|
||||
}
|
||||
if (route?.metadata?.viewItem) {
|
||||
// 自动打开右侧面板
|
||||
if (!studioStore.showRightPanel) {
|
||||
studioStore.setShowRightPanel(true);
|
||||
}
|
||||
const viewItem = route.metadata.viewItem;
|
||||
viewItem.response = response;
|
||||
viewItem.action = action;
|
||||
viewItem.description = route.description || viewItem.description;
|
||||
// @ts-ignore
|
||||
viewItem._id = Date.now();
|
||||
studioStore.addMessage(viewItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
setIsLoading(false);
|
||||
}
|
||||
return <div className="h-full flex flex-col border-l border-gray-300 bg-white">
|
||||
<div style={{ height: '3rem' }} className="flex items-center justify-between px-4 border-b border-gray-300 bg-gray-50">
|
||||
<div className="text-sm text-gray-600">智能体</div>
|
||||
</div>
|
||||
<div style={{ height: 'calc(100% - 3rem)' }} className="overflow-auto">
|
||||
<QueryViewMessages type="component" />
|
||||
</div>
|
||||
<div className="flex items-center gap-2 px-4 py-3 border-t border-gray-300 bg-white">
|
||||
<input
|
||||
type="text"
|
||||
placeholder="输入消息..."
|
||||
value={text}
|
||||
onChange={(e) => setText(e.target.value)}
|
||||
onKeyDown={(e) => e.key === 'Enter' && onSend()}
|
||||
className="flex-1 px-3 py-2 border border-gray-300 rounded-md bg-white text-black placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-gray-800 transition-all"
|
||||
/>
|
||||
<button
|
||||
onClick={onSend}
|
||||
disabled={isLoading}
|
||||
className="px-4 py-2 bg-black hover:bg-gray-900 disabled:bg-gray-400 text-white font-medium rounded-md transition-colors duration-200 flex-shrink-0"
|
||||
>
|
||||
{isLoading ? '发送中...' : '发送'}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
Reference in New Issue
Block a user