聊《做过测试的人学大模型,哪些经验可以直接迁移?》之前,先说一句实在的:别急着背概念,先看它在真实项目里到底解决什么问题。
摘要
目录
- 真实案例:我带的一个AI测试项目
- 权限:被很多人忽略的"第一道墙"
- 日志与可观测:Agent决策链追踪
- 失败原因:三类错误的区分方式
- 质量评估:从"能不能跑"到"跑得好不好"
- 简历表达建议
- 总结
真实案例:我带的一个AI测试项目

去年我接手了一个电商Agent的项目,做的是智能客服问答。系统用RAG架构,接入公司内部的订单数据库和产品知识库。产品侧要求的是"用户问什么答什么",但作为测试,我拿到需求后第一时间不是想怎么测通过率,而是先问了一句话:"它的权限边界在哪里?"
这个项目当时踩过的坑,我觉得很有代表性,也直接对应了我后来写进简历里的几个核心模块。
先说整体背景:这是一个基于LangChain的Agent,底层用的是OpenAI的API,知识库是通过Milvus向量数据库管理的。测试目标包括:功能正确性、权限合规性、可观测性、稳定性。其中前两个,传统测试同学容易上手;后两个,才是这次转型真正拉开差距的地方。
我做的第一件事,是搭了一个简化的本地测试环境——用一个开源模型加一个小型向量库,模拟真实RAG Agent的核心链路:用户输入 → 意图路由 → 工具调用 → 结果生成。这个环境的好处是,可以在权限配置上灵活调整,便于做各种边界测试。
权限:被很多人忽略的"第一道墙"

面试过程中我发现一个问题:很多候选人做的项目,能跑通Demo就算完事,但真到企业级应用,权限往往是最先暴露问题的地方。
我的项目中,有一个很典型的case:知识库的某些数据是有访问权限控制的——比如订单金额、用户联系方式这类敏感字段,只有特定角色才能查询。但Agent在做检索时,没有做权限过滤,直接把所有数据都返回给了用户。
这属于典型的"数据平权"问题。解决思路是把权限检查放在检索层之前,而不是靠后期的人工审核。具体来说,就是让Agent在执行查询前,先获取当前用户的角色权限信息,然后根据权限白名单过滤知识库的返回结果。
代码层面,我是在ChatOpenAI之前加了一个中间件,专门做权限校验:
from typing import List, Dict
class PermissionFilter:
def __init__(self, user_role: str):
self.user_role = user_role
self.access_levels = self._load_access_config()
def _load_access_config(self) -> Dict:
# 从配置文件加载角色权限表
return {
"customer_service": ["public_info"],
"order_manager": ["order_info", "public_info"],
"admin": ["all"]
}
def filter_documents(
self,
docs: List[Dict],
user_role: str
) -> List[Dict]:
allowed = self.access_levels.get(user_role, ["public_info"])
if "all" in allowed:
return docs
filtered = []
for doc in docs:
if doc.get("access_level") in allowed:
filtered.append(doc)
return filtered
# 使用示例
filter = PermissionFilter(user_role="customer_service")
filtered_docs = filter.filter_documents(raw_docs, "customer_service")
这个代码的核心逻辑是先过滤再给模型,而不是让模型自行判断。输出是所有文档中符合当前角色权限的部分,异常处理方面,如果用户角色不在配置表里,默认只返回public_info级别的数据。
我在这个模块上花的时间不少,主要是调试不同角色的权限交叉访问问题。有一次发现某个manager角色的权限配置少了一个level,导致订单查询返回了空结果,排查了很久才发现是配置表的key拼错了。
日志与可观测:Agent决策链追踪
这是测试转AI最核心需要补的一个能力。传统测试只需要看接口返回对不对,但Agent的决策过程是多步的,每一步都可能出问题。
我做了一个工具调用链的日志追踪方案,核心思路是:每次工具调用都要记录输入参数、输出结果、耗时,并关联到同一个request_id。这样排查问题时,可以从最终回答反推整个决策过程。
排查过程是这样的:有一次发现Agent对同一个问题,有时候回答准确,有时候回答错误。通过日志追踪发现,问题出在tool选择上——模型在某些情况下选择了错误的工具,而且错误选择后没有重试机制。这个case让我深刻体会到,Agent的"随机性"在测试阶段就必须被充分覆盖。
具体实现上,我用了一个自定义的Callback类,继承LangChain的BaseCallbackHandler:
import time
import logging
from langchain.callbacks.base import BaseCallbackHandler
from typing import Any, Dict, List
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
class TraceCallback(BaseCallbackHandler):
def __init__(self, request_id: str):
self.request_id = request_id
self.tool_calls = []
def on_tool_start(
self,
serialized: Dict,
input_str: str,
**kwargs
) -> Any:
tool_name = serialized.get("name", "unknown")
self.tool_calls.append({
"tool": tool_name,
"input": input_str,
"start_time": time.time(),
"request_id": self.request_id
})
logger.info(
f"[{self.request_id}] Tool start: {tool_name}, "
f"input: {input_str[:100]}"
)
def on_tool_end(self, output: str, **kwargs) -> None:
last_call = self.tool_calls[-1]
last_call["output"] = output
last_call["end_time"] = time.time()
last_call["duration"] = (
last_call["end_time"] - last_call["start_time"]
)
logger.info(
f"[{self.request_id}] Tool end: {last_call['tool']}, "
f"duration: {last_call['duration']:.2f}s"
)
def on_llm_end(self, response: Any, **kwargs) -> None:
logger.info(
f"[{self.request_id}] LLM response received"
)
代码解释:输入是requestid,用于关联同一次请求的所有日志;核心逻辑是在工具调用开始和结束时记录时间戳和参数;输出是结构化的日志信息,方便后续查询和回溯;异常处理方面,如果工具调用失败,会在ontool_end里记录错误信息。

失败原因:三类错误的区分方式
在做这个项目期间,我遇到很多看似奇怪的问题,后来总结成三类:业务错误、配置错误、环境错误。
业务错误是最难定位的。比如模型返回了错误的工具名,这不是代码bug,而是prompt设计的问题。有一次我在prompt里写"根据用户问题选择合适的工具",结果模型在某些边界case下会误判。排查思路是:先把模型输出的raw response打印出来,看它到底看到了什么、想了什么,再针对性地调整prompt。
配置错误相对好排查。有一次向量库的embedding模型和检索用的模型不一致,导致检索效果很差。排查动作是对比两边的配置项,发现embedding模型版本号不一致,统一后问题解决。这类错误的特征是:配置项之间有不一致,通过diff配置表可以快速定位。
环境错误一般出现在部署阶段。比如某个依赖包的版本在本地能跑但在服务器上不行。这类问题的排查思路是:先在开发环境复现,再看线上环境的docker镜像和依赖配置,找出差异点。
区分这三类错误的方法很简单:业务错误改prompt,配置错误改配置,环境错误改部署。但真正难的是在问题发生时,快速判断它属于哪一类。我后来的习惯是,遇到问题先问自己:是模型"想错了",还是配置"设错了",还是环境"装错了"。
质量评估:从"能不能跑"到"跑得好不好"
这是测试转AI最容易忽视的一环。Demo能跑通,只能证明功能可用,不能证明质量达标。
我在这个项目里建立了一套轻量级的质量评估指标,包括:回答准确率、权限覆盖率、工具调用成功率、平均响应时间、错误率。这些指标不是拍脑袋定的,而是根据业务场景和业务方的真实需求来的。
比如权限覆盖率,我的目标是99%以上,因为任何一条越权返回都可能是严重的合规问题。工具调用成功率是95%,因为这个指标直接关系用户体验。
评估方法是用一批标准测试集,每轮迭代都跑一遍,看指标变化趋势。这样做的好处是可以量化改进效果,也能在出问题时有据可查。
简历表达建议
如果你要做类似的项目,简历上不要只写"做了RAG Agent",要把权限、日志、评估这些维度写出来。比如:
- "设计并实现了基于角色的权限过滤中间件,覆盖3类用户角色,权限覆盖率提升至99%"
- "构建工具调用链追踪系统,实现单请求全链路日志记录,平均问题定位时间从2小时缩短至15分钟"
- "建立Agent质量评估体系,定义5项核心指标,支持A/B测试和版本对比"
这些表达的关键是:有场景、有做法、有结果。面试官问起来的时候,能讲清楚为什么这么做、怎么做、做得怎么样。
适用边界
该方案适合可观测的小规模实践;当规模、实时性或合规要求变化时,需要重新评估限制和兜底。
总结
测试转AI测试,最大的门槛不是技术栈,而是思维方式的转换。传统测试关注功能是否正确,AI测试还要关注决策链是否可观测、权限边界是否清晰、质量指标是否可量化。
这个转型过程中,我走了不少弯路,但也积累了一些可以复用的经验。希望这篇文章能给你一些参考,少走一些我已经踩过的坑。
资料展示
下面是我整理的AI大模型学习资料和工具包预览,适合收藏后按主题逐步学习。



需要这份AI大模型资料清单的话,在评论区回复「清单」即可;我会根据大家的问题继续补充对应的实战内容。


1512

被折叠的 条评论
为什么被折叠?



