优化ai问片流式处理,系统提示词增加日期,优化决策json提取
This commit is contained in:
@@ -73,13 +73,22 @@ function transformToSSE(
|
|||||||
|
|
||||||
return new ReadableStream({
|
return new ReadableStream({
|
||||||
async start(controller) {
|
async start(controller) {
|
||||||
|
let buffer = ''; // 缓冲区,用于保存不完整的行
|
||||||
try {
|
try {
|
||||||
while (true) {
|
while (true) {
|
||||||
const { done, value } = await reader.read();
|
const { done, value } = await reader.read();
|
||||||
if (done) break;
|
if (done) break;
|
||||||
|
|
||||||
const chunk = decoder.decode(value, { stream: true });
|
const chunk = decoder.decode(value, { stream: true });
|
||||||
const lines = chunk.split('\n').filter((line) => line.trim() !== '');
|
// 将新chunk与缓冲区拼接
|
||||||
|
const text = buffer + chunk;
|
||||||
|
// 按换行符分割,最后一个元素可能是不完整的行
|
||||||
|
const parts = text.split('\n');
|
||||||
|
// 保存最后一个不完整的行到缓冲区
|
||||||
|
buffer = parts.pop() || '';
|
||||||
|
|
||||||
|
// 处理完整的行
|
||||||
|
const lines = parts.filter((line) => line.trim() !== '');
|
||||||
|
|
||||||
for (const line of lines) {
|
for (const line of lines) {
|
||||||
if (line.startsWith('data: ')) {
|
if (line.startsWith('data: ')) {
|
||||||
@@ -126,6 +135,34 @@ function transformToSSE(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 处理缓冲区中剩余的数据
|
||||||
|
if (buffer.trim()) {
|
||||||
|
const line = buffer.trim();
|
||||||
|
if (line.startsWith('data: ')) {
|
||||||
|
const data = line.slice(6).trim();
|
||||||
|
if (data && data !== '[DONE]') {
|
||||||
|
try {
|
||||||
|
const json = JSON.parse(data);
|
||||||
|
let text = '';
|
||||||
|
if (provider === 'claude') {
|
||||||
|
if (json.type === 'content_block_delta') {
|
||||||
|
text = json.delta?.text || '';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
text = json.choices?.[0]?.delta?.content || '';
|
||||||
|
}
|
||||||
|
if (text) {
|
||||||
|
controller.enqueue(
|
||||||
|
new TextEncoder().encode(`data: ${JSON.stringify({ text })}\n\n`)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Parse final buffer error:', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Stream error:', error);
|
console.error('Stream error:', error);
|
||||||
controller.error(error);
|
controller.error(error);
|
||||||
|
|||||||
@@ -211,13 +211,22 @@ export default function AIChatPanel({
|
|||||||
}
|
}
|
||||||
|
|
||||||
let assistantMessage = '';
|
let assistantMessage = '';
|
||||||
|
let buffer = ''; // 缓冲区,用于保存不完整的行
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
const { done, value } = await reader.read();
|
const { done, value } = await reader.read();
|
||||||
if (done) break;
|
if (done) break;
|
||||||
|
|
||||||
const chunk = decoder.decode(value, { stream: true });
|
const chunk = decoder.decode(value, { stream: true });
|
||||||
const lines = chunk.split('\n').filter((line) => line.trim() !== '');
|
// 将新chunk与缓冲区拼接
|
||||||
|
const text = buffer + chunk;
|
||||||
|
// 按换行符分割,最后一个元素可能是不完整的行
|
||||||
|
const parts = text.split('\n');
|
||||||
|
// 保存最后一个不完整的行到缓冲区
|
||||||
|
buffer = parts.pop() || '';
|
||||||
|
|
||||||
|
// 处理完整的行
|
||||||
|
const lines = parts.filter((line) => line.trim() !== '');
|
||||||
|
|
||||||
for (const line of lines) {
|
for (const line of lines) {
|
||||||
if (line.startsWith('data: ')) {
|
if (line.startsWith('data: ')) {
|
||||||
@@ -250,6 +259,33 @@ export default function AIChatPanel({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 处理缓冲区中剩余的数据
|
||||||
|
if (buffer.trim()) {
|
||||||
|
const line = buffer.trim();
|
||||||
|
if (line.startsWith('data: ')) {
|
||||||
|
const data = line.slice(6);
|
||||||
|
if (data && data !== '[DONE]') {
|
||||||
|
try {
|
||||||
|
const json = JSON.parse(data);
|
||||||
|
const text = json.text || '';
|
||||||
|
if (text) {
|
||||||
|
assistantMessage += text;
|
||||||
|
setMessages((prev) => {
|
||||||
|
const newMessages = [...prev];
|
||||||
|
newMessages[newMessages.length - 1] = {
|
||||||
|
role: 'assistant',
|
||||||
|
content: assistantMessage,
|
||||||
|
};
|
||||||
|
return newMessages;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error('解析最终缓冲区数据失败:', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// 处理非流式响应
|
// 处理非流式响应
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
|
|||||||
@@ -346,14 +346,19 @@ function formatSearchResults(
|
|||||||
* 清理可能被代码块包裹的JSON字符串
|
* 清理可能被代码块包裹的JSON字符串
|
||||||
*/
|
*/
|
||||||
function cleanJsonResponse(content: string): string {
|
function cleanJsonResponse(content: string): string {
|
||||||
// 去除可能的markdown代码块标记
|
|
||||||
let cleaned = content.trim();
|
let cleaned = content.trim();
|
||||||
|
|
||||||
// 移除 ```json 或 ``` 开头
|
// 尝试提取代码块中的内容(支持前面有说明文字的情况)
|
||||||
cleaned = cleaned.replace(/^```(?:json)?\s*\n?/i, '');
|
const codeBlockMatch = cleaned.match(/```(?:json)?\s*\n?([\s\S]*?)\n?```/i);
|
||||||
|
if (codeBlockMatch) {
|
||||||
// 移除 ``` 结尾
|
cleaned = codeBlockMatch[1].trim();
|
||||||
cleaned = cleaned.replace(/\n?```\s*$/, '');
|
} else {
|
||||||
|
// 如果没有代码块,尝试提取第一个 { 到最后一个 } 之间的内容
|
||||||
|
const jsonMatch = cleaned.match(/\{[\s\S]*\}/);
|
||||||
|
if (jsonMatch) {
|
||||||
|
cleaned = jsonMatch[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return cleaned.trim();
|
return cleaned.trim();
|
||||||
}
|
}
|
||||||
@@ -690,8 +695,15 @@ export async function orchestrateDataSources(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 4. 构建系统提示词
|
// 4. 构建系统提示词
|
||||||
|
// 获取UTC+8时区的日期
|
||||||
|
const now = new Date();
|
||||||
|
const utc8Date = new Date(now.getTime() + 8 * 60 * 60 * 1000);
|
||||||
|
const today = utc8Date.toISOString().split('T')[0]; // YYYY-MM-DD格式
|
||||||
let systemPrompt = `你是 MoonTVPlus 的 AI 影视助手,专门帮助用户发现和了解影视内容。
|
let systemPrompt = `你是 MoonTVPlus 的 AI 影视助手,专门帮助用户发现和了解影视内容。
|
||||||
|
|
||||||
|
## 当前日期
|
||||||
|
${today}
|
||||||
|
|
||||||
## 你的能力
|
## 你的能力
|
||||||
- 提供影视推荐(基于豆瓣热门榜单和TMDB数据)
|
- 提供影视推荐(基于豆瓣热门榜单和TMDB数据)
|
||||||
- 回答影视相关问题(剧情、演员、评分等)
|
- 回答影视相关问题(剧情、演员、评分等)
|
||||||
|
|||||||
Reference in New Issue
Block a user