fix(ai-nutritionist): 图文问答注入营养师 system prompt(test-0415 反馈3-4)

- 旧版多模态消息仅有用户 parts,模型无领域上下文,常回退到通用客套话
- 新增 SYSTEM_NUTRITIONIST:专业中文营养师人设 + 慢病饮食知识 + 非食物兜底
- 仅在含 image_url 时注入,避免影响纯文字流式(3-2)回归
- image 类型用户提示从「请分析这张图片」改为「识别食物,给营养成分与饮食建议」

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
msh-agent
2026-05-03 03:18:27 +08:00
parent 8868d6f948
commit 31f909247e

View File

@@ -717,30 +717,42 @@ export default {
* @returns {Array} messages 数组 [{role, content}]
*/
buildChatMessages(content, type) {
// test-0415 反馈3-4图文问答需明确告诉模型「请基于图片识别食物 / 营养建议」,
// 否则模型容易回退到通用客套话;纯文字场景仍走旧逻辑(避免影响 3-2 流式回归)
const SYSTEM_NUTRITIONIST = '你是一名专业的中文营养师助手。当用户消息中包含图片image_url请先识别图片中的食物或菜品然后基于其常见营养成分能量、蛋白质、脂肪、碳水、钾、磷、钠、嘌呤等给出针对慢性肾病/痛风/糖尿病人群的饮食建议;若图片不是食物,请明确说明「这张图不是食物」并简短回应用户。'
if (type === 'text') {
return [{ role: 'user', content: typeof content === 'string' ? content : String(content) }]
}
if (type === 'image') {
// 图片:尝试构建多模态消息
let fileInfo = content
if (typeof fileInfo === 'string') {
try { fileInfo = JSON.parse(fileInfo) } catch (e) { /* 非JSON */ }
}
const imageUrl = (fileInfo && fileInfo.url) || (fileInfo && fileInfo.path) || ''
if (imageUrl) {
return [{
role: 'user',
content: [
{ type: 'image_url', image_url: { url: imageUrl } },
{ type: 'text', text: '请分析这张图片' }
]
}]
return [
{ role: 'system', content: SYSTEM_NUTRITIONIST },
{
role: 'user',
content: [
{ type: 'image_url', image_url: { url: imageUrl } },
{ type: 'text', text: '请基于这张图片识别食物,给出营养成分与饮食建议' }
]
}
]
}
return [{ role: 'user', content: '我发送了一张图片,请帮我分析' }]
}
// multimodal直接传多模态 parts
// multimodal直接传多模态 parts;含 image_url 时附加 system prompt 引导模型分析图片
const parts = Array.isArray(content) ? content : [{ type: 'text', text: String(content) }]
return [{ role: 'user', content: parts }]
const hasImage = parts.some((p) => p && (p.type === 'image_url' || p.image_url))
const messages = []
if (hasImage) {
messages.push({ role: 'system', content: SYSTEM_NUTRITIONIST })
}
messages.push({ role: 'user', content: parts })
return messages
},
async sendToAI(content, type) {