agents-image.md 14 KB

大模型多模态能力(图片分析)调用示例总结(适配Claude Code规则)

本示例基于 Angular框架 + fmode-ng SDK,调用多模态大模型(fmode-1.6-cn)的「视觉识别+文本理解」能力,实现道德与法治题目图片的全流程处理(图片OCR识别→结构化提取→答案解析→追问互动),核心是通过「视觉模态」突破纯文本输入限制,实现图片内容的语义化解析。

一、核心基础信息

1.1 技术栈与依赖

类别 具体内容
框架 Angular(依赖注入@Injectable,服务级复用)
核心SDK fmode-ng(提供多模态调用completionJSON、聊天流式输出FmodeChatCompletion
数据存储 Parse(SurveyItem存储题目/解析,SurveyLog存储搜题日志)
多模态模型 fmode-1.6-cn(支持视觉+文本双模态,核心用于图片题目识别)

1.2 关键常量定义(固定配置)

// 1. 多模态任务模板(关联后端模板逻辑)
export const DaofaQuestionRecognitionTplCode = 'daofa-question-recognition-tpl'; // 题目识别模板
export const DaofaQATplCode = 'daofa-qa-tpl'; // 问答/追问模板
// 2. 多模态模型标识(必须指定支持视觉的模型)
export const DaofaModel = 'fmode-1.6-cn';

二、多模态核心能力:图片题目识别(核心流程)

2.1 功能描述

通过大模型「视觉能力」解析上传的题目图片(如试卷、练习册拍照),将图片中的文字(题干、选项、材料)转化为结构化JSON数据(题型、关键词、选项等),是整个流程的「多模态入口」。

2.2 代码实现与规则要点

/**
 * 多模态核心:识别题目图片(视觉+文本)
 * @param options.images 图片数组(需为Base64格式,大模型视觉输入标准格式)
 * @param options.onProgressChange 进度回调(如“正在识别题目内容...”)
 * @returns 结构化存储的题目对象(SurveyItem)
 */
async recognizeQuestion(options: {
  images: string[]; // 关键:图片输入(Base64字符串数组,支持多图)
  onProgressChange?: (progress: string) => void;
  loading?: any;
}): Promise<FmodeObject> {
  return new Promise(async (resolve, reject) => {
    try {
      // 1. 多模态提示词设计(规则1:结构化提示,强制输出JSON格式)
      const prompt = `请识别图片中的道德与法治题目,并按以下JSON格式输出:
{
  "questionType": "题型(single-choice/multi-choice/judge/short-answer/material-analysis)",
  "title": "题目标题或简述",
  "content": "完整的题目内容",
  "options": [{"label": "A", "value": "选项内容"}],
  "material": "材料内容(如有)",
  "keywords": ["关键词1", "关键词2"] // 如“宪法、权利、义务”
}
要求:
1. 准确识别题干、选项、材料的文字(含标点);
2. 严格匹配题型枚举值,不可自定义;
3. 关键词需贴合道德与法治学科核心概念。`;

      // 2. 输出格式约束(规则2:提供JSON示例,降低大模型输出偏差)
      const output = `{
  "questionType": "single-choice",
  "title": "宪法基本权利题",
  "content": "下列属于公民基本权利的是?",
  "options": [{"label": "A", "value": "依法纳税"}],
  "material": "",
  "keywords": ["公民基本权利", "宪法"]
}`;

      // 3. 调用多模态能力(规则3:视觉识别必须配置vision=true + 传入images)
      const questionData = await completionJSON(
        prompt,          // 文本提示词
        output,          // 输出格式示例
        (content) => {   // 增量回调(可选,用于进度更新)
          options.loading?.message = `正在识别题目...${content?.length || 0}字`;
        },
        2,               // 重试次数
        {
          model: DaofaModel,  // 指定多模态模型
          vision: true,       // 启用视觉能力(核心开关)
          images: options.images  // 传入图片数组(Base64)
        }
      );

      // 4. 结果校验(规则4:多模态输出必须先判空,避免后续流程异常)
      if (!questionData || !questionData.content) {
        throw new Error('题目识别结果为空(图片无有效文字或识别失败)');
      }

      // 5. 数据持久化(规则5:识别结果映射到标准存储对象SurveyItem)
      const surveyItem = await this.saveSurveyItem({
        type: 'daofa',                  // 学科标识
        title: questionData.title || '未命名道德与法治题目',
        content: questionData.content,  // 识别后的题干
        images: options.images,         // 关联原始图片
        keywords: questionData.keywords || [],
        options: questionData.options || [],
        createOptions: {
          tpl: DaofaQuestionRecognitionTplCode,
          params: {
            questionType: questionData.questionType,
            recognitionMode: 'image-ocr', // 标记为“图片OCR识别”来源
            material: questionData.material
          }
        }
      });

      resolve(surveyItem);
    } catch (err: any) {
      reject(new Error(`图片识别失败:${err.message || '未知错误'}`));
    }
  });
}

三、配套能力:基于多模态结果的文本延伸

3.1 功能1:答案与解析生成(纯文本模态,依赖图片识别结果)

将图片识别后的结构化题目(题干、选项、题型)传入大模型,生成符合「道德与法治学科规范」的解析(含标准答案、知识点、易错点等),支持流式输出(实时更新内容)。

async generateAnswer(options: {
  surveyItem: FmodeObject; // 图片识别后的题目对象
  onContentChange?: (content: string) => void; // 流式内容回调
}): Promise<FmodeObject> {
  return new Promise(async (resolve, reject) => {
    try {
      // 1. 从图片识别结果中提取关键信息(规则:复用多模态输出的结构化数据)
      const { content: questionContent, options: questionOptions } = options.surveyItem.attributes;
      const questionType = options.surveyItem.get('createOptions').params.questionType;

      // 2. 结构化提示词(规则:按学科要求分模块,确保解析专业度)
      const prompt = `作为道德与法治教师,解析以下题目:
题目类型:${questionType}
题目内容:${questionContent}
${questionOptions.length ? `选项:\n${questionOptions.map(opt => `${opt.label}. ${opt.value}`).join('\n')}` : ''}

要求按以下格式输出:
【标准答案】(选择题需标注选项,如“A”;简答题需分点)
【知识点】(关联教材章节/法律条文,如“《宪法》第33条 公民在法律面前一律平等”)
【解题思路】(初中生易懂,结合生活实例)
【易错点】(如“混淆‘权利’与‘义务’,依法纳税是义务而非权利”)
【知识拓展】(关联时政热点,如“2024年法治宣传周主题”)`;

      // 3. 流式调用(规则:使用FmodeChatCompletion实现实时内容更新)
      const completion = new (await import('fmode-ng/lib/core/agent')).FmodeChatCompletion(
        [{ role: 'user', content: prompt }], // 上下文
        { model: DaofaModel }
      );

      const subscription = completion.sendCompletion({ isDirect: true }).subscribe({
        next: (message: any) => {
          const content = message.content || '';
          options.onContentChange?.(content); // 实时更新前端解析内容

          // 当输出完成时,保存解析结果并标记选择题正确答案
          if (message.complete && content) {
            options.surveyItem.set('answer', content);
            // 提取正确答案(如从“【标准答案】A”中匹配选项)
            if (questionType.includes('choice')) {
              const correctLabel = this.extractCorrectAnswer(content);
              if (correctLabel) {
                const updatedOptions = questionOptions.map(opt => ({
                  ...opt,
                  check: opt.label === correctLabel // 标记正确选项
                }));
                options.surveyItem.set('options', updatedOptions);
              }
            }
            options.surveyItem.save().then(resolve);
          }
        },
        error: (err) => reject(new Error(`解析生成失败:${err.message}`))
      });
    } catch (err: any) {
      reject(new Error(`解析生成失败:${err.message}`));
    }
  });
}

3.2 功能2:用户追问处理(上下文模态,闭环互动)

基于已识别的题目和解析,处理用户的后续疑问(如“为什么这个选项不对?”),需传入历史上下文确保回答连贯性。

async handleQuestion(options: {
  parentQuestion: FmodeObject; // 原始题目(图片识别结果)
  userQuestion: string;        // 用户追问内容
}): Promise<FmodeObject> {
  return new Promise(async (resolve, reject) => {
    try {
      // 1. 拼接上下文(规则:必须包含原始题目+已有解析,避免回答脱离场景)
      const parentContent = options.parentQuestion.get('content');
      const parentAnswer = options.parentQuestion.get('answer');
      const prompt = `基于以下题目和解析,回答学生的追问:
题目内容:${parentContent}
已有解析:${parentAnswer}
学生追问:${options.userQuestion}

要求:
1. 针对追问精准回应,不偏离原始题目;
2. 用“启发式”语言(如“你可以先回顾‘权利与义务的区别’,再看选项是否符合权利的定义”);
3. 引用教材/法律条文时标注出处。`;

      // 2. 调用大模型并保存追问记录
      const completion = new (await import('fmode-ng/lib/core/agent')).FmodeChatCompletion(
        [{ role: 'user', content: prompt }],
        { model: DaofaModel }
      );

      completion.sendCompletion({ isDirect: true }).subscribe({
        next: async (message: any) => {
          if (message.complete && message.content) {
            // 保存追问记录到SurveyItem(类型为daofa-qa)
            const qaItem = await this.saveQuestionAnswer({
              parent: options.parentQuestion,
              question: options.userQuestion,
              answer: message.content
            });
            resolve(qaItem);
          }
        },
        error: (err) => reject(new Error(`追问回答失败:${err.message}`))
      });
    } catch (err: any) {
      reject(new Error(`追问处理失败:${err.message}`));
    }
  });
}

四、Claude Code 核心规则提炼

4.1 多模态调用强制规则

  1. 视觉能力启用:调用completionJSON实现图片识别时,必须在参数中配置 { vision: true, images: 图片数组(Base64格式), model: 多模态模型(如fmode-1.6-cn) },缺一不可;
  2. 图片格式要求images参数需为「Base64字符串数组」(前端上传图片需先转Base64,不可直接传URL);
  3. 输出稳定性:必须通过「结构化提示词+输出示例」约束大模型输出(如指定JSON字段、枚举值),避免非结构化内容导致解析异常。

4.2 提示词设计规范

  1. 学科约束:针对垂直领域(如道德与法治),需在提示词中明确「专业要求」(如“引用法律条文需标注出处”“符合初中生认知水平”);
  2. 格式约束:输出需分模块/JSON结构时,必须提供「完整示例」(如output参数的JSON模板),降低大模型输出偏差;
  3. 上下文完整性:追问/解析生成时,必须包含「原始题目+历史结果」(如parentContent+parentAnswer),避免回答脱离场景。

4.3 流程链路规则

  1. 数据依赖:图片识别(recognizeQuestion)是前置流程,后续的解析生成(generateAnswer)、追问(handleQuestion)必须依赖其输出的SurveyItem对象;
  2. 结果校验:多模态输出(questionData)需先校验「非空+关键字段存在」(如contentquestionType),再进入存储/后续流程;
  3. 流式处理:使用FmodeChatCompletion时,需通过next事件处理增量内容(实时更新UI),complete事件触发结果保存,避免数据丢失。

4.4 数据存储规则

  1. 对象区分SurveyItem用于存储「题目/解析/追问」,需通过type字段区分(daofa=原始题目,daofa-qa=追问记录);
  2. 日志跟踪SurveyLog需记录「搜题模式(图片/OCR)、上传图片、识别耗时」,用于后续统计与问题排查;
  3. 关联关系:追问记录(daofa-qa类型SurveyItem)需通过parent字段关联原始题目,确保上下文链路可追溯。

五、完整流程链路

graph TD
    A[用户上传道德与法治题目图片] --> B[图片转Base64格式]
    B --> C[调用recognizeQuestion(多模态视觉识别)]
    C --> D{识别结果校验}
    D -- 失败 --> E[抛出“识别失败”错误]
    D -- 成功 --> F[保存为SurveyItem(type=daofa)]
    F --> G[调用generateAnswer(文本解析生成)]
    G --> H[流式输出解析内容,标记选择题正确答案]
    H --> I[用户发起追问(如“为什么B选项错误?”)]
    I --> J[调用handleQuestion(上下文互动)]
    J --> K[保存为SurveyItem(type=daofa-qa,关联parent题目)]
    K --> L[更新SurveyLog(记录追问次数、耗时)]