fix: 停止迁移复活默认模型供应商/模型;AI聊天媒体生成改为异步(修复视频请求失败)
- migrations/002_init_data.sql: 移除 model_providers/models 的 INSERT IGNORE 种子,重启容器不再复活 deepseek/openai/通义千问等默认供应商与模型,改由用户在后台大模型库自行维护
- chat.py: 图像/视频生成分支改为立即返回占位(generating=true),后台 asyncio 任务轮询 AGNES 并回写消息内容,避免最长 5 分钟同步轮询阻塞 HTTP 请求导致前端「发送失败:请求失败」
- ChatPage.tsx: 发送后若 assistant_message.generating,每 3s 轮询 getMessages 直至内容更新;页面刷新时若仍有「⏳」占位继续轮询;卸载清理定时器
This commit is contained in:
1 parent
b7f76c3e92
commit
5d1370156e
3 files changed
+121
-21
No files matched your search
@@ -565,8 +565,67 @@ const ChatPage: React.FC = () => {
|
||||
}
|
||||
};
|
||||
loadMessages();
|
||||
|
||||
// 页面刷新时若仍有「⏳」占位的媒体消息,继续轮询后端回写结果
|
||||
mapped.forEach((m) => {
|
||||
if (m.role === 'assistant' && typeof m.content === 'string' && m.content.startsWith('⏳')) {
|
||||
startMediaPolling(id, m.id);
|
||||
}
|
||||
});
|
||||
}, [id]);
|
||||
|
||||
// 媒体(图像/视频)异步生成轮询:后端先返回「⏳」占位,前端定时拉取该消息最新内容并回写
|
||||
const pollMediaRef = useRef<Record<string, ReturnType<typeof setInterval> | null>>({});
|
||||
|
||||
const stopMediaPolling = (msgId: string) => {
|
||||
const t = pollMediaRef.current[msgId];
|
||||
if (t) {
|
||||
clearInterval(t);
|
||||
pollMediaRef.current[msgId] = null;
|
||||
}
|
||||
};
|
||||
|
||||
const startMediaPolling = (convId: string, msgId: string) => {
|
||||
if (pollMediaRef.current[msgId]) return; // 已在轮询
|
||||
let ticks = 0;
|
||||
const timer = setInterval(async () => {
|
||||
ticks += 1;
|
||||
try {
|
||||
const res = await chatAPI.getMessages(convId);
|
||||
const msgs: any[] = unwrapList(res);
|
||||
const updated = msgs.find((m: any) => m.id === msgId);
|
||||
if (!updated) {
|
||||
stopMediaPolling(msgId);
|
||||
return;
|
||||
}
|
||||
const content: string = updated.content || '';
|
||||
if (content.startsWith('⏳')) {
|
||||
if (ticks > 120) stopMediaPolling(msgId); // ~6 分钟兜底
|
||||
return;
|
||||
}
|
||||
// 生成完成:回写消息内容
|
||||
setMessages(prev => prev.map(m => m.id === msgId ? {
|
||||
...m,
|
||||
content,
|
||||
tokenUsed: updated.tokenUsed ?? updated.token_used ?? m.tokenUsed,
|
||||
createdAt: updated.createdAt || updated.created_at || m.createdAt,
|
||||
used_skills: updated.usedSkills ?? updated.used_skills ?? m.used_skills,
|
||||
} : m));
|
||||
stopMediaPolling(msgId);
|
||||
} catch (e) {
|
||||
if (ticks > 120) stopMediaPolling(msgId); // 网络异常兜底
|
||||
}
|
||||
}, 3000);
|
||||
pollMediaRef.current[msgId] = timer;
|
||||
};
|
||||
|
||||
// 卸载时清理所有轮询定时器
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
Object.values(pollMediaRef.current).forEach(t => t && clearInterval(t));
|
||||
};
|
||||
}, []);
|
||||
|
||||
// Load knowledge bases, agents, skills for attachment dropdowns
|
||||
useEffect(() => {
|
||||
knowledgeAPI.getBases().then((res: any) => {
|
||||
@@ -821,6 +880,11 @@ const ChatPage: React.FC = () => {
|
||||
return [...filtered, ...newMsgs];
|
||||
});
|
||||
|
||||
// 媒体异步生成:启动轮询,待后端回写后自动刷新
|
||||
if (data.assistant_message?.generating) {
|
||||
startMediaPolling(selectedConversation!.id, data.assistant_message.id);
|
||||
}
|
||||
|
||||
// Refresh conversations to update lastMessage
|
||||
loadConversations();
|
||||
|
||||
|
||||
Reference in new issue
Block a user