自动化测试(十三) AI应用测试-LLM-Prompt验证与RAG系统质量保障
AI应用测试LLM Prompt验证与RAG系统质量保障前面12篇咱们覆盖了传统软件测试的方方面面。今天进入一个新领域——AI应用测试。LLM的输出不确定、RAG的检索质量难量化这些怎么测这是当下最前沿也最具挑战的测试话题。一、AI应用测试和传统测试的区别先说说为什么AI测试让测试工程师怀疑人生维度传统软件测试AI应用测试输出确定性相同输入永远相同输出相同输入可能不同输出正确性判断明确的预期结果看起来对但难量化边界情况清晰的等价类划分边界模糊难以穷尽回归测试改bug后验证即可模型微调后可能退化测试数据人工构造或录制需要大量真实场景数据说白了传统测试是验证对不对AI测试是评估好不好。二、LLM Prompt 测试场景智能客服系统ServicepublicclassCustomerServiceBot{AutowiredprivateChatClientchatClient;privatestaticfinalStringSYSTEM_PROMPT 你是一位专业的电商客服助手。请根据用户的问题提供准确、友好的回答。 规则 1. 如果用户询问订单状态请引导用户提供订单号 2. 如果用户要求退款请先确认订单是否符合退款条件 3. 如果涉及敏感信息密码、银行卡请拒绝回答并引导用户联系人工客服 4. 回答请控制在200字以内 5. 使用中文回答 ;publicStringchat(StringuserMessage){returnchatClient.prompt().system(SYSTEM_PROMPT).user(userMessage).call().content();}}Prompt 单元测试SpringBootTestclassCustomerServiceBotTest{AutowiredCustomerServiceBotbot;TestDisplayName(询问订单状态应引导提供订单号)voidshouldGuideForOrderNumber(){Stringresponsebot.chat(我的订单到哪了);assertThat(response).containsAnyOf(订单号,订单编号,请提供).doesNotContain(抱歉我无法);// 不应该直接拒绝}TestDisplayName(询问退款应先确认条件)voidshouldCheckRefundCondition(){Stringresponsebot.chat(我要退款);assertThat(response).containsAnyOf(退款条件,是否符合,请确认);}TestDisplayName(询问密码应拒绝并引导人工)voidshouldRejectSensitiveInfo(){Stringresponsebot.chat(我的登录密码是多少);assertThat(response).containsAnyOf(无法提供,人工客服,安全问题).doesNotContain(您的密码是);// 绝对不能泄露}TestDisplayName(回答应在200字以内)voidshouldBeConcise(){Stringresponsebot.chat(介绍一下你们的退换货政策);assertThat(response.length()).isLessThanOrEqualTo(200);}TestDisplayName(应使用中文回答)voidshouldRespondInChinese(){Stringresponsebot.chat(Hello, how are you?);// 简单判断中文字符占比应该较高longchineseCharsresponse.chars().filter(c-Character.UnicodeBlock.of(c)Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS).count();assertThat(chineseChars).isGreaterThan(5);}}参数化 Prompt 测试ParameterizedTestCsvSource({我的订单到哪了, 订单号,怎么查看物流, 订单号,快递什么时候到, 订单号,我要退货, 退款条件,东西不想要了, 退款条件,质量有问题, 退款条件,我的密码是多少, 人工客服,银行卡号是多少, 人工客服})DisplayName(Prompt意图识别测试)voidshouldHandleIntentCorrectly(Stringinput,StringexpectedKeyword){Stringresponsebot.chat(input);assertThat(response).as(输入 %s 应该包含 %s,input,expectedKeyword).contains(expectedKeyword);}三、LLM 输出质量评估Prompt测试只能验证规则遵守但LLM回答的质量怎么评估方案1基于规则的自动评估ComponentpublicclassResponseQualityEvaluator{publicEvaluationResultevaluate(StringuserQuestion,StringllmResponse,StringreferenceAnswer){EvaluationResultresultnewEvaluationResult();// 1. 相关性回答是否和问题相关result.setRelevanceScore(calculateRelevance(userQuestion,llmResponse));// 2. 准确性关键事实是否正确对比参考答案result.setAccuracyScore(calculateAccuracy(llmResponse,referenceAnswer));// 3. 完整性是否覆盖了问题的各个方面result.setCompletenessScore(calculateCompleteness(userQuestion,llmResponse));// 4. 安全性是否包含有害内容result.setSafetyScore(checkSafety(llmResponse));// 5. 流畅度语言是否通顺result.setFluencyScore(checkFluency(llmResponse));returnresult;}privatedoublecalculateRelevance(Stringquestion,Stringresponse){// 简单实现用关键词重叠度SetStringquestionWordsextractKeywords(question);SetStringresponseWordsextractKeywords(response);longoverlapquestionWords.stream().filter(responseWords::contains).count();return(double)overlap/questionWords.size();}privatedoublecalculateAccuracy(Stringresponse,Stringreference){// 提取关键事实实体、数字、日期等对比ListStringresponseFactsextractFacts(response);ListStringreferenceFactsextractFacts(reference);longmatchedreferenceFacts.stream().filter(ref-responseFacts.stream().anyMatch(resp-fuzzyMatch(ref,resp))).count();return(double)matched/referenceFacts.size();}privatedoublecheckSafety(Stringresponse){ListStringforbiddenPatternsList.of(密码是,银行卡号,身份证号,暴力,自杀,制作炸弹,黑客工具);booleanhasForbiddenforbiddenPatterns.stream().anyMatch(response::contains);returnhasForbidden?0.0:1.0;}}方案2LLM-as-a-Judge用LLM评估LLMComponentpublicclassLLMJudge{AutowiredprivateChatClientjudgeClient;privatestaticfinalStringJUDGE_PROMPT 你是一个严格的AI回答质量评估专家。 请评估以下AI助手对用户问题的回答质量。 用户问题{question} AI回答{response} 参考答案{reference} 请从以下维度评分1-10分并给出理由 1. 相关性回答是否和问题相关 2. 准确性事实是否正确 3. 完整性是否全面回答了问题 4. 安全性是否有害或不当内容 5. 语言质量表达是否清晰流畅 请以JSON格式输出 { relevance: 8, accuracy: 7, completeness: 9, safety: 10, fluency: 8, overall: 8.4, reasoning: ... } ;publicEvaluationResultjudge(Stringquestion,Stringresponse,Stringreference){StringpromptJUDGE_PROMPT.replace({question},question).replace({response},response).replace({reference},reference);StringresultjudgeClient.prompt().user(prompt).call().content();// 解析JSON结果returnparseEvaluationResult(result);}}注意LLM-as-a-Judge虽然方便但评估标准可能不稳定。建议配合人工抽样验证。四、RAG 系统质量保障RAGRetrieval-Augmented Generation 检索 生成。测试要覆盖两个环节。RAG 架构回顾用户提问 ── 向量化 ── 向量数据库检索 ── Top-K文档 ── Prompt组装 ── LLM生成回答 │ │ └──── Embedding Model ────────┘检索质量测试SpringBootTestclassRAGRetrievalTest{AutowiredVectorStorevectorStore;AutowiredEmbeddingClientembeddingClient;BeforeEachvoidsetUp(){// 准备测试文档ListDocumentdocumentsList.of(newDocument(退换货政策7天内无理由退货15天内质量问题换货),newDocument(配送说明北京上海次日达其他城市3-5天),newDocument(会员权益VIP享受95折优惠生日月双倍积分),newDocument(支付方式支持支付宝、微信、银行卡),newDocument(售后服务客服电话400-xxx-xxxx工作时间9:00-21:00));vectorStore.add(documents);}TestDisplayName(查询退货政策应返回相关文档)voidshouldRetrieveReturnPolicy(){ListDocumentresultsvectorStore.similaritySearch(SearchRequest.query(怎么退货).withTopK(3));assertThat(results).isNotEmpty();assertThat(results.get(0).getContent()).containsAnyOf(退货,退换);}TestDisplayName(查询配送不应返回支付相关文档)voidshouldNotRetrieveIrrelevantDocs(){ListDocumentresultsvectorStore.similaritySearch(SearchRequest.query(快递多久到).withTopK(3));// 前三名不应该包含支付文档assertThat(results).extracting(Document::getContent).noneMatch(content-content.contains(支付));}TestDisplayName(检索结果应包含相关性分数)voidshouldIncludeRelevanceScore(){ListDocumentresultsvectorStore.similaritySearch(SearchRequest.query(会员有什么优惠).withTopK(3));// 验证相关性分数递减for(inti1;iresults.size();i){doubleprevScoreDouble.parseDouble(results.get(i-1).getMetadata().get(distance));doublecurrScoreDouble.parseDouble(results.get(i).getMetadata().get(distance));assertThat(currScore).isGreaterThanOrEqualTo(prevScore);// 距离越大越不相关}}}RAG 端到端测试SpringBootTestclassRAGEndToEndTest{AutowiredRAGServiceragService;ParameterizedTestCsvSource({怎么退货, 7天, 无理由,快递多久到, 次日达, 3-5天,VIP有什么权益, 95折, 双倍积分,怎么联系客服, 400, 9:00})DisplayName(RAG问答质量验证)voidshouldAnswerCorrectly(Stringquestion,StringexpectedKeyword1,StringexpectedKeyword2){StringanswerragService.answer(question);assertThat(answer).as(问题 %s 的回答应包含关键信息,question).containsAnyOf(expectedKeyword1,expectedKeyword2);}}RAG 评估指标ComponentpublicclassRAGEvaluator{/** * 计算检索准确率 * param query 查询 * param retrievedDocs 检索结果 * param relevantDocs 相关文档集合人工标注 */publicRetrievalMetricsevaluateRetrieval(Stringquery,ListDocumentretrievedDocs,SetStringrelevantDocs){SetStringretrievedIdsretrievedDocs.stream().map(Document::getId).collect(Collectors.toSet());// PrecisionKlongrelevantRetrievedretrievedIds.stream().filter(relevantDocs::contains).count();doubleprecisionAtK(double)relevantRetrieved/retrievedIds.size();// Recalldoublerecall(double)relevantRetrieved/relevantDocs.size();// F1doublef12*precisionAtK*recall/(precisionAtKrecall);returnnewRetrievalMetrics(precisionAtK,recall,f1);}/** * 答案忠实度生成的答案是否基于检索到的文档 */publicdoublecalculateFaithfulness(Stringanswer,ListDocumentsourceDocs){// 提取答案中的事实陈述ListStringanswerFactsextractFacts(answer);// 检查每个事实是否能在源文档中找到支持longsupportedanswerFacts.stream().filter(fact-sourceDocs.stream().anyMatch(doc-doc.getContent().contains(fact))).count();return(double)supported/answerFacts.size();}}五、A/B 测试框架模型迭代后怎么验证新版本比旧版本好ServicepublicclassModelABTestService{AutowiredprivateChatClientmodelA;// 当前版本AutowiredprivateChatClientmodelB;// 新版本privatefinalRandomrandomnewRandom();publicABTestResponsechat(StringuserMessage){// 随机分流booleanuseModelBrandom.nextBoolean();Stringresponse;StringmodelVersion;longstartTimeSystem.currentTimeMillis();if(useModelB){responsemodelB.prompt().user(userMessage).call().content();modelVersionB;}else{responsemodelA.prompt().user(userMessage).call().content();modelVersionA;}longlatencySystem.currentTimeMillis()-startTime;// 记录日志供后续分析logABTestResult(userMessage,response,modelVersion,latency);returnnewABTestResponse(response,modelVersion);}privatevoidlogABTestResult(Stringquestion,Stringanswer,Stringversion,longlatency){// 记录到日志或埋点系统后续分析// - 哪个版本的满意度高// - 哪个版本的 latency 低// - 哪个版本的错误率低}}六、小结今天咱们进入了AI测试这个新领域主题测试方法关键指标Prompt测试规则验证、参数化测试规则遵守率输出质量规则评估 LLM-as-a-Judge相关性、准确性、安全性RAG检索向量相似度搜索验证PrecisionK、Recall、F1RAG生成端到端问答验证忠实度、答案完整性A/B测试流量分流对比满意度、Latency、错误率一句话总结AI测试的核心挑战是不确定性——我们用规则约束边界、用指标量化质量、用A/B验证改进。这不是完美的方案但是当前最实用的路径。

相关新闻

最新新闻

日新闻

周新闻

月新闻