package cn.iocoder.yudao.module.qcreport.service.aiimport.document; import java.util.List; /** * 一个文件被适配器抽取后的中间结果。 *
* 刻意不是树、也不是 HTML:它只是「这份文件能交给模型的东西是什么」这个更小的问题的答案。 * 树要表达版式,HTML 要表达样式,两者都会把「模型能看见什么」放大到不可控;这里只留两个通道, * 迫使下游(提示词构造、调用计划)不必再考虑第三种形态。 * *
* 它属于「抽取出来的文本长什么样」这条契约,所以和 {@code text} 放在一处, * 由生产者({@link OfficeImportAdapter})与解释者({@code QcReportTemplatePromptBuilder}) * 共用一份,避免两边各写一个字面量后各自漂移。 *
* 为什么不能留空:{@code w:vMerge} 的续格在 Word 里表示「这一格与上一行是同一个值」,
* 但 POI 取出来就是空串。留空的话,模型区分不出「合并续格」与「原件本来就没填」,
* 于是整张表看起来是一层平铺的检验项,看不出分组结构。
*/
public static final String VERTICAL_MERGE_MARK = "↑同上";
/**
* 抽取通道。
*/
public enum Channel {
/** 有文本层,整份文件拼成一段文本,一次模型调用 */
TEXT,
/** 无文本层(扫描件/照片),逐页转图,每页一次模型调用 */
IMAGES
}
/**
* IMAGES 通道里的一页图。
*
* @param bytes 图片字节,执行器负责转成裸 base64
* @param mimeType 形如 {@code image/png} 的裸类型,不带 {@code data:} 前缀
* @param label 页标签,用于拼错误与提示文案,例如「扫描件.pdf 第 2 页」
*/
public record ImagePart(byte[] bytes, String mimeType, String label) {
}
/**
* 文本通道的工厂。{@code notes} 允许为空表示没有软提示。
*/
public static QcReportDocumentExtract ofText(String text, int pageCount, String extractor,
List