
说明文中类名 / 方法签名均在本地spring-ai 1.1.3的 jar 中核对过文档里几处 1.0 时代的旧写法已在「踩坑清单」标出。1. 什么叫评估测试普通测试断言确定值assertEquals(2, 1 1)但 AI 的输出是自然语言、每次还不一样没法硬断言。评估测试 再找一个裁判模型按规则对 AI 的输出打分 / 判定把不确定的生成结果变成可断言的true / false或分数。目的发现幻觉hallucination、答非所问、回答脱离给定上下文。定位属于集成测试会真实调用模型有费用、有延迟、结果不完全稳定。常见评估维度相关性relevancy、事实一致性 / groundedness、答案正确性。Spring AI 的抽象就是一个函数式接口FunctionalInterfacepublicinterfaceEvaluator{EvaluationResponseevaluate(EvaluationRequestevaluationRequest);}2. 两个数据类publicclassEvaluationRequest{privatefinalStringuserText;// 用户原始输入privatefinalListContentdataList;// 上下文数据例如 RAG 检索到的文档privatefinalStringresponseContent;// AI 模型的回答内容}publicclassEvaluationResponse{booleanisPass();// 核心是否通过评估floatgetScore();// 分数StringgetFeedback();// 裁判模型的反馈MapString,ObjectgetMetadata();// 元数据}1.1.3 实测构造器重载有三个newEvaluationRequest(StringuserText,StringresponseContent);newEvaluationRequest(ListDocumentdataList,StringresponseContent);newEvaluationRequest(StringuserText,ListDocumentdataList,StringresponseContent);3. 相关性评估器 RelevancyEvaluator判什么回答是否贴合用户问题 检索到的上下文。主要用于验证 RAG 流程质量上下文有没有真被用上。框架内置的默认提示模板是英文的模型只回答 YES / NO含义如下Your task is to evaluate if the response for the query is in line with the context information provided. You have two options to answer. Either YES or NO. Answer YES, if the response for the query is in line with context information otherwise NO. Query: {query} Response:{response} Context: {context} Answer:想让裁判模型用中文理解或统一团队语言可以换成中文版模板占位符必须是 query / response / context 三个你的任务是判断下面的回答是否与提供的上下文信息一致。 你只有两个选择YES 或 NO。 如果回答与上下文信息一致回答 YES否则回答 NO。 问题 {query} 回答 {response} 上下文 {context} 答案集成测试用法验证 RAG 流程TestvoidevaluateRelevancy(){Stringquestion阿纳克莱图斯和比尔巴的冒险发生在什么地方;RetrievalAugmentationAdvisorragAdvisorRetrievalAugmentationAdvisor.builder().documentRetriever(VectorStoreDocumentRetriever.builder().vectorStore(pgVectorStore).build()).build();ChatResponsechatResponseChatClient.builder(chatModel).build().prompt(question).advisors(ragAdvisor).call().chatResponse();EvaluationRequestevaluationRequestnewEvaluationRequest(question,// 原始问题chatResponse.getMetadata().get(RetrievalAugmentationAdvisor.DOCUMENT_CONTEXT),// RAG 检索到的上下文chatResponse.getResult().getOutput().getText()// 模型回答);RelevancyEvaluatorevaluatornewRelevancyEvaluator(ChatClient.builder(chatModel));EvaluationResponseevaluationResponseevaluator.evaluate(evaluationRequest);assertThat(evaluationResponse.isPass()).isTrue();}关键点dataList不能随便传必须是这一次 RAG 真正检索到的上下文从RetrievalAugmentationAdvisor.DOCUMENT_CONTEXT取否则评估没有意义。4. 自定义模板通过.promptTemplate()传入自己的PromptTemplate可以用任意TemplateRenderer默认基于 StringTemplate 的StPromptTemplate。硬性要求模板必须包含三个占位符—— query、response、context。RelevancyEvaluatorevaluatorRelevancyEvaluator.builder().chatClientBuilder(ChatClient.builder(chatModel)).promptTemplate(PromptTemplate.builder().renderer(StTemplateRenderer.builder().startDelimiterToken().endDelimiterToken().build()).template( 问题query 回答response 上下文context 回答是否由上下文支持只输出 YES 或 NO。 ).build()).build();5. 事实核查评估器 FactCheckingEvaluator判什么回答中的陈述claim是否被给定文档document逻辑支持 —— 用来检测幻觉。框架内置提示模板英文Document: {document} Claim: {claim}中文含义 / 想中文化时可用文档{document} 陈述{claim}模型建议用更小更省的专用模型例如 Bespoke-Minicheck可通过 Ollama 跑比 GPT-4 便宜得多。TestvoidtestFactChecking(){OllamaApiollamaApinewOllamaApi(http://localhost:11434);ChatModelchatModelnewOllamaChatModel(ollamaApi,OllamaChatOptions.builder().model(BESPOKE_MINICHECK).numPredict(2).temperature(0.0d).build());varfactCheckingEvaluatornewFactCheckingEvaluator(ChatClient.builder(chatModel));Stringcontext地球是距离太阳第三近的行星也是目前已知唯一存在生命的天体。;Stringclaim地球是距离太阳第四近的行星。;EvaluationRequestevaluationRequestnewEvaluationRequest(context,Collections.emptyList(),claim);EvaluationResponseevaluationResponsefactCheckingEvaluator.evaluate(evaluationRequest);assertFalse(evaluationResponse.isPass(),该陈述与上下文矛盾应当判为不通过);}6. ⚠ 1.1.3 踩坑清单文档 vs 实际文档 / 教程写法1.1.3 实际org.springframework.ai.evaluation.RelevancyEvaluatororg.springframework.ai.chat.evaluation.RelevancyEvaluatororg.springframework.ai.evaluation.FactCheckingEvaluatororg.springframework.ai.chat.evaluation.FactCheckingEvaluatorEvaluationRequest(ListContent dataList, ...)实际是ListDocumentEvaluationRequest/EvaluationResponse/Evaluator在org.springframework.ai.evaluationspring-ai-commonsnew FactCheckingEvaluator(chatClientBuilder)该构造器是protected只能用FactCheckingEvaluator.builder(builder)或FactCheckingEvaluator.forBespokeMinicheck(builder)即导入应该是importorg.springframework.ai.chat.evaluation.RelevancyEvaluator;// spring-ai-client-chatimportorg.springframework.ai.chat.evaluation.FactCheckingEvaluator;// spring-ai-client-chatimportorg.springframework.ai.evaluation.EvaluationRequest;// spring-ai-commonsimportorg.springframework.ai.evaluation.EvaluationResponse;// spring-ai-commonsimportorg.springframework.ai.evaluation.Evaluator;// spring-ai-commons照抄旧文档会直接Cannot resolve symbol/ 构造器不可见。7. 落地建议评估测试会真实烧 token建议用Disabled或Tag(evaluation)隔离别让mvn test每次都跑。评估模型可以和生成模型不同强模型生成、专/小模型评判是常见省钱姿势。裁判模型本身也有偏差isPass() false只能当信号不能直接当结论。写 JUnit 5 assertThat需要spring-boot-starter-test只引入junit:junit:3.8.1的模块跑不了。本模块用的是内存SimpleVectorStore评估前必须先灌库否则检索上下文为空、评估必然失败。