feat: 更新AI教练服务,支持处理多个图片URL,优化饮食分析逻辑。调整相关DTO以支持数组格式的图片URL,并修改默认视觉模型为'qwen-vl-max'。
This commit is contained in:
@@ -42,7 +42,7 @@ export class AiCoachController {
|
||||
userId,
|
||||
conversationId,
|
||||
userContent,
|
||||
imageUrl: body.imageUrl,
|
||||
imageUrls: body.imageUrls,
|
||||
});
|
||||
let text = '';
|
||||
for await (const chunk of readable) {
|
||||
@@ -62,7 +62,7 @@ export class AiCoachController {
|
||||
userId,
|
||||
conversationId,
|
||||
userContent,
|
||||
imageUrl: body.imageUrl,
|
||||
imageUrls: body.imageUrls,
|
||||
});
|
||||
|
||||
readable.on('data', (chunk) => {
|
||||
|
||||
@@ -103,7 +103,7 @@ export class AiCoachService {
|
||||
});
|
||||
// 默认选择通义千问对话模型(OpenAI兼容名),可通过环境覆盖
|
||||
this.model = this.configService.get<string>('DASHSCOPE_MODEL') || 'qwen-flash';
|
||||
this.visionModel = this.configService.get<string>('DASHSCOPE_VISION_MODEL') || 'qwen-vl-plus';
|
||||
this.visionModel = this.configService.get<string>('DASHSCOPE_VISION_MODEL') || 'qwen-vl-max';
|
||||
}
|
||||
|
||||
async createOrAppendMessages(params: {
|
||||
@@ -200,7 +200,7 @@ export class AiCoachService {
|
||||
conversationId: string;
|
||||
userContent: string;
|
||||
systemNotice?: string;
|
||||
imageUrl?: string;
|
||||
imageUrls?: string[];
|
||||
}): Promise<Readable> {
|
||||
// 解析指令(如果以 # 开头)
|
||||
const commandResult = this.parseCommand(params.userContent);
|
||||
@@ -227,8 +227,8 @@ export class AiCoachService {
|
||||
}
|
||||
} else if (commandResult.command === 'diet') {
|
||||
// 使用视觉模型分析饮食图片
|
||||
if (params.imageUrl) {
|
||||
const dietAnalysis = await this.analyzeDietImage(params.imageUrl);
|
||||
if (params.imageUrls) {
|
||||
const dietAnalysis = await this.analyzeDietImage(params.imageUrls);
|
||||
messages.push({
|
||||
role: 'user',
|
||||
content: `用户通过拍照记录饮食,图片分析结果如下:\n${dietAnalysis}`
|
||||
@@ -418,7 +418,7 @@ export class AiCoachService {
|
||||
* @param imageUrl 图片URL
|
||||
* @returns 饮食分析结果
|
||||
*/
|
||||
private async analyzeDietImage(imageUrl: string): Promise<string> {
|
||||
private async analyzeDietImage(imageUrls: string[]): Promise<string> {
|
||||
try {
|
||||
const prompt = `请分析这张食物图片,识别其中的食物种类、分量,并提供以下信息:
|
||||
|
||||
@@ -445,11 +445,11 @@ export class AiCoachService {
|
||||
role: 'user',
|
||||
content: [
|
||||
{ type: 'text', text: prompt },
|
||||
{ type: 'image_url', image_url: { url: imageUrl } as any },
|
||||
...imageUrls.map((imageUrl) => ({ type: 'image_url', image_url: { url: imageUrl } as any })),
|
||||
] as any,
|
||||
},
|
||||
],
|
||||
temperature: 0,
|
||||
temperature: 1,
|
||||
});
|
||||
|
||||
this.logger.log(`diet image analysis result: ${completion.choices?.[0]?.message?.content}`);
|
||||
|
||||
@@ -25,8 +25,9 @@ export class AiChatRequestDto {
|
||||
|
||||
@ApiProperty({ required: false, description: '当用户要记体重时的图片URL(电子秤等)' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
imageUrl?: string;
|
||||
@IsArray()
|
||||
@IsString({ each: true })
|
||||
imageUrls?: string[];
|
||||
|
||||
@ApiProperty({ required: false, description: '是否启用流式输出', default: true })
|
||||
@IsOptional()
|
||||
|
||||
Reference in New Issue
Block a user