package cn.iocoder.yudao.module.qcreport.service.aiimport.llm; /** * 一次待执行的大模型调用。 *
* 由 {@link QcReportLlmCallPlanner} 纯函数算出,交给薄执行器真正发出去。 * 拆成「先算计划、再执行」是为了让多页 / 多文件 / 超预算这些控制流可以被单测完整覆盖—— * 否则只能靠 mock 掉 {@code AiChatApi} 才能测,那测的是 mock 不是逻辑。 *
* 每个调用自带全部入参(含 TEXT 通道的正文),执行器不需要回看抽取结果。 * * @param kind 调用方式,决定走 {@code chat} 还是 {@code chatWithImage} * @param sourceLabel 来源标签,形如「扫描件.pdf 第 2 页」,用于软提示与错误文案 * @param text TEXT 通道的正文;IMAGE 通道恒为空串 * @param imageBase64 IMAGE 通道的**裸 base64**(不含 {@code data:image/png;base64,} 前缀, * 因为 {@code AiChatApiImpl} 直接对它做 Base64 解码);TEXT 通道恒为空串 * @param mimeType IMAGE 通道的裸 MIME 类型,如 {@code image/png} */ public record QcReportLlmCall( Kind kind, String sourceLabel, String text, String imageBase64, String mimeType) { /** * 调用方式。 */ public enum Kind { /** 纯文本,一次调用搞定整份文件 */ TEXT, /** 多模态,一次调用只认一张图,所以逐页一调 */ IMAGE } public static QcReportLlmCall ofText(String sourceLabel, String text) { return new QcReportLlmCall(Kind.TEXT, sourceLabel, text, "", ""); } public static QcReportLlmCall ofImage(String sourceLabel, String imageBase64, String mimeType) { return new QcReportLlmCall(Kind.IMAGE, sourceLabel, "", imageBase64, mimeType); } }