代码优化

This commit is contained in:
董宏凯 committed 2026-05-28 22:35:05 +08:00
1 parent 214e794451
commit 2371364911
5 files changed
+62 -548

No files matched your search

+11 -57
View File
@@ -61,47 +61,28 @@ export default function StrategyRoutes() {
/>
{/* 任务管理 */}
<Route path="task-management" element={<TaskManagement />}>
<Route index element={<Navigate to="xk-task-jc" replace />} />
{/* XK任务 */}
<Route
path="xk-task-jc"
element={
<TaskXkFrom
gopath={'#/pageIndie/pageHome/pageSwrw'}
/>
}
element={<TaskXkFrom gopath="#/pageIndie/pageHome/pageSwrw" />}
/>
<Route
path="xk-task-dispatch"
element={
<TaskXkFrom
gopath={'#/pageIndie/pageJczl'}
/>
}
element={<TaskXkFrom gopath="#/pageIndie/pageJczl" />}
/>
{/* pg中任务 */}
<Route
path="effect-task-pg"
element={
<TaskPgFrom
gopath="task"
/>
}
element={<TaskPgFrom gopath="task" />}
/>
<Route
path="effect-action-pg"
element={
<TaskPgFrom
gopath="xd"
/>
}
element={<TaskPgFrom gopath="xd" />}
/>
<Route
path="effect-info-pg"
element={
<TaskPgFrom
gopath="info"
/>
}
element={<TaskPgFrom gopath="info" />}
/>
{/* COH中任务 */}
<Route
@@ -114,7 +95,7 @@ export default function StrategyRoutes() {
/>
}
/>
<Route
<Route
path="plan-task/plan-task-fx"
element={
<TaskAnalyzes
@@ -124,7 +105,7 @@ export default function StrategyRoutes() {
/>
}
/>
<Route
<Route
path="plan-task/plan-task-action"
element={
<ActionAnalyzes
@@ -135,36 +116,9 @@ export default function StrategyRoutes() {
}
/>
{/* MNTY任务 */}
<Route
path="mnty-task-mechanism"
element={
<XingdongTyPage
title="XDTY任务"
category="MNTY任务"
subCategory="MNTY任务"
/>
}
/>
<Route
path="mnty-task-plan"
element={
<FanganTyPage
title="方案TY任务"
category="MNTY任务"
subCategory="MNTY任务"
/>
}
/>
<Route
path="mnty-task-zsty"
element={
<XXTyPage
title="XXTY任务"
category="MNTY任务"
subCategory="MNTY任务"
/>
}
/>
<Route path="mnty-task-mechanism" element={<XingdongTyPage />} />
<Route path="mnty-task-plan" element={<FanganTyPage />} />
<Route path="mnty-task-zsty" element={<XXTyPage />} />
</Route>
{/* 资源管理 */}
<Route
@@ -1074,17 +1074,38 @@ const GeneralQA: React.FC<{
};
/**
* 处理真实多轮 RAG 请求。
* 统一的多轮 SSE 生成请求。
*
* handleRun / handleTaskRun / handleHxRun / newsReportRun 原本是四份几乎一致的拷贝,
* 仅请求地址和少量 side 处理细节不同。这里抽成一个函数,差异通过 options 严格保留:
* - passSideToToolCall:是否把 side 透传给 handleToolCall(对比模式下写入对应面板)
* - guardHistoryBySide:是否仅在非对比模式(!side)时落库,避免对比模式重复落库
* - logCompareResult:仅影响 done 时调试日志打印的对象(compareResult / messageList)
*
* 多轮接口采用 SSE:每行 `data:` 都描述一个事件。组件根据事件类型分别更新 taskId、工具调用、
* 最终回答和引用来源。当前用户入口暂时走本地模拟,此方法保留给接口连通后切换使用。
* 最终回答和引用来源。
*/
const handleRun = async (query: string, side: 'left' | 'right' | null = null) => {
const runMultiRoundStream = async (
url: string,
query: string,
side: 'left' | 'right' | null = null,
options: {
passSideToToolCall?: boolean;
guardHistoryBySide?: boolean;
logCompareResult?: boolean;
} = {},
) => {
const {
passSideToToolCall = false,
guardHistoryBySide = false,
logCompareResult = false,
} = options;
setError(null);
setIsLoading(true);
setIsPreConnectLoading(true);
try {
const response = await fetch(`${generateUrl}/generate`, {
const response = await fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ prompt: query }),
@@ -1109,20 +1130,14 @@ const GeneralQA: React.FC<{
};
if (!side) {
state.current.messageList.push(assistantMessage); // 数据存储
// 接口连通后再展示多轮检索主题与过程
setMessages((prev) => [...prev, assistantMessage]);
} else if (side === 'left' || side === 'right') {
state.current.compareResult[state.current.compareIndex][side].thinkingTrace = createMultiRoundStreamTrace();
updatePane(side, (pane) => {
return {
...pane,
thinkingTrace: createMultiRoundStreamTrace(),
};
});
updatePane(side, (pane) => ({ ...pane, thinkingTrace: createMultiRoundStreamTrace() }));
}
const reader = response.body.getReader();
// 保存 reader 引用,用于"停止生成"功能
// 保存 reader 引用,用于“停止生成”功能
if (!side) {
readerRef.current = reader;
} else {
@@ -1135,8 +1150,8 @@ const GeneralQA: React.FC<{
while (true) {
const { done, value } = await reader.read();
if (done) {
console.log('聊天记录', state.current.compareResult);
if (!side) {
console.log('聊天记录', logCompareResult ? state.current.compareResult : state.current.messageList);
if (!guardHistoryBySide || !side) {
chatHistoryAddSearch();
}
break;
@@ -1163,7 +1178,7 @@ const GeneralQA: React.FC<{
break;
}
case 'tool_call': {
handleToolCall(data as ToolCallData, assistantId, side);
handleToolCall(data as ToolCallData, assistantId, passSideToToolCall ? side : null);
break;
}
case 'message': {
@@ -1228,464 +1243,27 @@ const GeneralQA: React.FC<{
}
};
/**
* 处理任务检索 请求。
*
* 多轮接口采用 SSE:每行 `data:` 都描述一个事件。组件根据事件类型分别更新 taskId、工具调用、
* 最终回答和引用来源。当前用户入口暂时走本地模拟,此方法保留给接口连通后切换使用。
*/
const handleTaskRun = async (query: string, side: 'left' | 'right' | null = null) => {
setError(null);
setIsLoading(true);
setIsPreConnectLoading(true);
// 多轮 RAG 检索:透传 side、仅非对比模式落库、日志打印 compareResult。
const handleRun = (query: string, side: 'left' | 'right' | null = null) =>
runMultiRoundStream(`${generateUrl}/generate`, query, side, {
passSideToToolCall: true,
guardHistoryBySide: true,
logCompareResult: true,
});
try {
const response = await fetch(`${taskChatUrl}/generate`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ prompt: query }),
});
// 任务检索:透传 side,但 done 时无条件落库。
const handleTaskRun = (query: string, side: 'left' | 'right' | null = null) =>
runMultiRoundStream(`${taskChatUrl}/generate`, query, side, {
passSideToToolCall: true,
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
// 画像检索:不透传 side,done 时无条件落库。
const handleHxRun = (query: string, side: 'left' | 'right' | null = null) =>
runMultiRoundStream(`${taskChatUrl}/generate_b2`, query, side);
if (!response.body) {
throw new Error('Response body is null');
}
setIsPreConnectLoading(false);
const assistantId = `assistant-${Date.now()}`;
const assistantMessage: Message = {
id: assistantId,
role: 'assistant',
content: '',
timestamp: new Date(),
thinkingTrace: createMultiRoundStreamTrace(),
};
if (!side) {
state.current.messageList.push(assistantMessage); // 数据存储
// 接口连通后再展示多轮检索主题与过程
setMessages((prev) => [...prev, assistantMessage]);
} else if (side === 'left' || side === 'right') {
state.current.compareResult[state.current.compareIndex][side].thinkingTrace = createMultiRoundStreamTrace();
updatePane(side, (pane) => {
return {
...pane,
thinkingTrace: createMultiRoundStreamTrace(),
};
});
}
const reader = response.body.getReader();
if (!side) {
readerRef.current = reader;
} else {
compareReaderRef.current[side] = reader;
}
const decoder = new TextDecoder();
let buffer = '';
try {
while (true) {
const { done, value } = await reader.read();
if (done) {
console.log('聊天记录', state.current.messageList);
chatHistoryAddSearch();
break;
}
buffer += decoder.decode(value, { stream: true });
const lines = buffer.split('\n');
const lastLine = lines.pop();
buffer = lastLine || '';
for (const line of lines) {
if (!line.startsWith('data: ')) continue;
try {
const parsedData = JSON.parse(line.slice(6)) as {
event: string;
data: any;
};
const { event, data } = parsedData;
switch (event) {
case 'task_created': {
taskIdRef.current = data?.task_id || null;
break;
}
case 'tool_call': {
handleToolCall(data as ToolCallData, assistantId, side);
break;
}
case 'message': {
if (typeof data === 'string') {
setMessages((prevMessages) => prevMessages.map((msg) => {
if (msg.id !== assistantId || !msg.thinkingTrace) return msg;
return {
...msg,
thinkingTrace: {
...msg.thinkingTrace,
finalAnswerMarkdown: `${msg.thinkingTrace.finalAnswerMarkdown}${data}`,
},
};
}));
}
break;
}
case 'references': {
const refs = Array.isArray(data?.references) ? data.references : [];
const mappedRefs = refs.map(mapReferenceToSource);
setSearchProcess((prev) => ({
...prev,
hits: mappedRefs.length,
}));
setMessages((prevMessages) => prevMessages.map((msg) => (
msg.id === assistantId
? { ...msg, sources: mappedRefs }
: msg
)));
break;
}
case 'done': {
setIsLoading(false);
break;
}
default:
console.log(`未知事件类型: ${event}`, data);
}
} catch (parseError) {
console.error('JSON解析错误:', parseError);
console.error('原始数据:', line.slice(6));
}
}
}
} finally {
if (readerRef.current) {
readerRef.current.releaseLock();
readerRef.current = null;
}
}
} catch (runError) {
console.error('处理请求时发生错误:', runError);
setIsLoading(false);
setError(runError instanceof Error ? runError.message : '发生未知错误,请稍后重试');
setIsPreConnectLoading(false);
} finally {
// 无论成功还是失败,都要重置加载状态和解锁提交
setIsPreConnectLoading(false);
setIsLoading(false);
submitLockRef.current = false;
handleStopCompareSide(side);
}
};
/**
* 处理画像检索 请求。
*
* 多轮接口采用 SSE:每行 `data:` 都描述一个事件。组件根据事件类型分别更新 taskId、工具调用、
* 最终回答和引用来源。当前用户入口暂时走本地模拟,此方法保留给接口连通后切换使用。
*/
const handleHxRun = async (query: string, side: 'left' | 'right' | null = null) => {
setError(null);
setIsLoading(true);
setIsPreConnectLoading(true);
try {
const response = await fetch(`${taskChatUrl}/generate_b2`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ prompt: query }),
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
if (!response.body) {
throw new Error('Response body is null');
}
setIsPreConnectLoading(false);
const assistantId = `assistant-${Date.now()}`;
const assistantMessage: Message = {
id: assistantId,
role: 'assistant',
content: '',
timestamp: new Date(),
thinkingTrace: createMultiRoundStreamTrace(),
};
if (!side) {
state.current.messageList.push(assistantMessage); // 数据存储
// 接口连通后再展示多轮检索主题与过程
setMessages((prev) => [...prev, assistantMessage]);
} else if (side === 'left' || side === 'right') {
state.current.compareResult[state.current.compareIndex][side].thinkingTrace = createMultiRoundStreamTrace();
updatePane(side, (pane) => {
return {
...pane,
thinkingTrace: createMultiRoundStreamTrace(),
};
});
}
const reader = response.body.getReader();
if (!side) {
readerRef.current = reader;
} else {
compareReaderRef.current[side] = reader;
}
const decoder = new TextDecoder();
let buffer = '';
try {
while (true) {
const { done, value } = await reader.read();
if (done) {
console.log('聊天记录', state.current.messageList);
chatHistoryAddSearch();
break;
}
buffer += decoder.decode(value, { stream: true });
const lines = buffer.split('\n');
const lastLine = lines.pop();
buffer = lastLine || '';
for (const line of lines) {
if (!line.startsWith('data: ')) continue;
try {
const parsedData = JSON.parse(line.slice(6)) as {
event: string;
data: any;
};
const { event, data } = parsedData;
switch (event) {
case 'task_created': {
taskIdRef.current = data?.task_id || null;
break;
}
case 'tool_call': {
handleToolCall(data as ToolCallData, assistantId);
break;
}
case 'message': {
if (typeof data === 'string') {
setMessages((prevMessages) => prevMessages.map((msg) => {
if (msg.id !== assistantId || !msg.thinkingTrace) return msg;
return {
...msg,
thinkingTrace: {
...msg.thinkingTrace,
finalAnswerMarkdown: `${msg.thinkingTrace.finalAnswerMarkdown}${data}`,
},
};
}));
}
break;
}
case 'references': {
const refs = Array.isArray(data?.references) ? data.references : [];
const mappedRefs = refs.map(mapReferenceToSource);
setSearchProcess((prev) => ({
...prev,
hits: mappedRefs.length,
}));
setMessages((prevMessages) => prevMessages.map((msg) => (
msg.id === assistantId
? { ...msg, sources: mappedRefs }
: msg
)));
break;
}
case 'done': {
setIsLoading(false);
break;
}
default:
console.log(`未知事件类型: ${event}`, data);
}
} catch (parseError) {
console.error('JSON解析错误:', parseError);
console.error('原始数据:', line.slice(6));
}
}
}
} finally {
if (readerRef.current) {
readerRef.current.releaseLock();
readerRef.current = null;
}
}
} catch (runError) {
console.error('处理请求时发生错误:', runError);
setIsLoading(false);
setError(runError instanceof Error ? runError.message : '发生未知错误,请稍后重试');
setIsPreConnectLoading(false);
} finally {
// 无论成功还是失败,都要重置加载状态和解锁提交
setIsPreConnectLoading(false);
setIsLoading(false);
submitLockRef.current = false;
handleStopCompareSide(side);
}
};
/**
* 处理画像检索 请求。
*
* 多轮接口采用 SSE:每行 `data:` 都描述一个事件。组件根据事件类型分别更新 taskId、工具调用、
* 最终回答和引用来源。当前用户入口暂时走本地模拟,此方法保留给接口连通后切换使用。
*/
const newsReportRun = async (query: string, side: 'left' | 'right' | null = null) => {
setError(null);
setIsLoading(true);
setIsPreConnectLoading(true);
try {
const response = await fetch(`${taskChatUrl}/generate_report`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ prompt: query }),
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
if (!response.body) {
throw new Error('Response body is null');
}
setIsPreConnectLoading(false);
const assistantId = `assistant-${Date.now()}`;
const assistantMessage: Message = {
id: assistantId,
role: 'assistant',
content: '',
timestamp: new Date(),
thinkingTrace: createMultiRoundStreamTrace(),
};
if (!side) {
state.current.messageList.push(assistantMessage); // 数据存储
// 接口连通后再展示多轮检索主题与过程
setMessages((prev) => [...prev, assistantMessage]);
} else if (side === 'left' || side === 'right') {
state.current.compareResult[state.current.compareIndex][side].thinkingTrace = createMultiRoundStreamTrace();
updatePane(side, (pane) => {
return {
...pane,
thinkingTrace: createMultiRoundStreamTrace(),
};
});
}
const reader = response.body.getReader();
if (!side) {
readerRef.current = reader;
} else {
compareReaderRef.current[side] = reader;
}
const decoder = new TextDecoder();
let buffer = '';
try {
while (true) {
const { done, value } = await reader.read();
if (done) {
console.log('聊天记录', state.current.messageList);
chatHistoryAddSearch();
break;
}
buffer += decoder.decode(value, { stream: true });
const lines = buffer.split('\n');
const lastLine = lines.pop();
buffer = lastLine || '';
for (const line of lines) {
if (!line.startsWith('data: ')) continue;
try {
const parsedData = JSON.parse(line.slice(6)) as {
event: string;
data: any;
};
const { event, data } = parsedData;
switch (event) {
case 'task_created': {
taskIdRef.current = data?.task_id || null;
break;
}
case 'tool_call': {
handleToolCall(data as ToolCallData, assistantId);
break;
}
case 'message': {
if (typeof data === 'string') {
setMessages((prevMessages) => prevMessages.map((msg) => {
if (msg.id !== assistantId || !msg.thinkingTrace) return msg;
return {
...msg,
thinkingTrace: {
...msg.thinkingTrace,
finalAnswerMarkdown: `${msg.thinkingTrace.finalAnswerMarkdown}${data}`,
},
};
}));
}
break;
}
case 'references': {
const refs = Array.isArray(data?.references) ? data.references : [];
const mappedRefs = refs.map(mapReferenceToSource);
setSearchProcess((prev) => ({
...prev,
hits: mappedRefs.length,
}));
setMessages((prevMessages) => prevMessages.map((msg) => (
msg.id === assistantId
? { ...msg, sources: mappedRefs }
: msg
)));
break;
}
case 'done': {
setIsLoading(false);
break;
}
default:
console.log(`未知事件类型: ${event}`, data);
}
} catch (parseError) {
console.error('JSON解析错误:', parseError);
console.error('原始数据:', line.slice(6));
}
}
}
} finally {
if (readerRef.current) {
readerRef.current.releaseLock();
readerRef.current = null;
}
}
} catch (runError) {
console.error('处理请求时发生错误:', runError);
setIsLoading(false);
setError(runError instanceof Error ? runError.message : '发生未知错误,请稍后重试');
setIsPreConnectLoading(false);
} finally {
// 无论成功还是失败,都要重置加载状态和解锁提交
setIsPreConnectLoading(false);
setIsLoading(false);
submitLockRef.current = false;
handleStopCompareSide(side);
}
};
// 新闻报告生成:不透传 side,done 时无条件落库。
const newsReportRun = (query: string, side: 'left' | 'right' | null = null) =>
runMultiRoundStream(`${taskChatUrl}/generate_report`, query, side);
/**
* 单一模式下的发送入口。
@@ -3,15 +3,9 @@ import "./css/iframe.css";
import { useTheme } from "@/contexts/ThemeContext";
interface FanganTyPageProps {
title: string;
category: string;
subCategory: string;
}
const TYURL = import.meta.env.VITE_AIPI_B2ACTOR_URL || "";
const FanganTyPage: React.FC<FanganTyPageProps> = () => {
const FanganTyPage: React.FC = () => {
const { theme } = useTheme();
const isDark = theme === "dark";
const [iframeUrl, setIframeUrl] = useState("");
@@ -3,15 +3,9 @@ import "./css/iframe.css";
import { useTheme } from "@/contexts/ThemeContext";
interface XXTyPageProps {
title: string;
category: string;
subCategory: string;
}
const TYURL = import.meta.env.VITE_AIPI_B2ACTOR_URL || "";
const XXTyPage: React.FC<XXTyPageProps> = () => {
const XXTyPage: React.FC = () => {
const { theme } = useTheme();
const isDark = theme === "dark";
const [iframeUrl, setIframeUrl] = useState("");
@@ -3,15 +3,9 @@ import "./css/iframe.css";
import { useTheme } from "@/contexts/ThemeContext";
interface XingdongTyPageProps {
title: string;
category: string;
subCategory: string;
}
const TYURL = import.meta.env.VITE_AIPI_B2ACTOR_URL || "";
const XingdongTyPage: React.FC<XingdongTyPageProps> = () => {
const XingdongTyPage: React.FC = () => {
const { theme } = useTheme();
const isDark = theme === "dark";
const [iframeUrl, setIframeUrl] = useState("");