“ 智能体debug最好的方式就是一个功能点一个功能点的测试;原因在于智能体不可控因素太多,会导致排查问题异常困难。”
最近在做智能体的过程中遇到了一个问题,就是流式返回的问题;刚开始为了方便,使用的是langgraph提供的create_react_agent接口;但使用过这个接口的人应该都知道,它提供的流式接口是一个伪流式或者说根本不是流式输出,因它的(a)stream流式方法中调用的是(a)invoke接口。
因此,后来还是选择使用自定义智能体的方式,使用StateGraph创建智能体。
def create_graph(self):
"""自定义智能体"""
graph_builder = StateGraph(MessagesState)
graph_builder.add_node("chatbot", self.chat_model)
graph_builder.add_node("tools", self.tool_node)
graph_builder.add_edge(START, "chatbot")
graph_builder.add_conditional_edges("chatbot",tools_condition)
graph_builder.add_edge("tools", "chatbot")
return graph_builder.compile()
智能体流式返回问题
从用户体验的角度出发,大家都知道大模型有流式返回的功能;但基于大模型的流式返回相对比较简单,当把大模型与工具相结合做成Agent智能体时,其复杂度就直线上升,出问题的概率也比较大。
智能体是大模型和工具的集合体,由于工具的存在就导致大模型的流式返回处理起来比较复杂;比如说调用工具时,必须要等到工具响应之后才能进行下一步,否则大模型无法获取工具的执行结果,那么调用工具就没了意义。
再有Langgraph为了解决节点调用过程中的数据通讯问题,使用了状态图(State)的方式进行数据传输;这样下层节点只能等上层节点执行完毕之后,才能从状态图中获取上层节点的执行结果;备注: 工具节点也是节点。

所以,这时影响智能体进行流式输出的因素就比较多了;可能是模型节点问题,工具节点问题,代码bug问题,工具包的版本问题,甚至是模型本身问题和模型的部署问题等等。
而作者这次遇到流式返回的问题,就是在模型的部署问题上;在智能体的测试过程中,一直都是一次性返回;刚开始一直以为是代码写的有bug导致无法流式返回,然后把代码改了又改,最后找到那些能正常流式返回的智能体代码,拿过来跑还是无法进行流式返回。
等发现这个问题又开始怀疑是不是环境问题,然后把两个环境的工具版本对照了一下,然后版本确实不太一样;但等把版本更新成统一版本时,还是无法流式返回。
智能体的流式返回有多种模式,不同的模式适合不同的业务场景。

这时才开始怀疑是不是模型的原因,但在测试智能体的过程中,也试过直接调用模型,但可以进行正常的流式返回;所以刚开始并没有怀疑模型的问题。
而最后经过替换第三方模型,发现确实是模型的问题;而这时又需要考虑是模型本身还是部署的原因;因为我们模型部署使用了nginx做了反向代理,并且使用的是ollama部署的。
然后经过一通测试,发现是ollama的版本问题导致无法正常流式输出。
经过这次问题,也发现了一个debug的方法;在智能体开发中,由于智能体本身的复杂性,其涉及的环节比较多,再加上大模型本身的不稳定性;就导致其问题排查过程非常困难。

因此,在智能体开发中比较好的debug方式就是,一个问题一个问题,一个节点一个节点的排查;比如说怀疑工具调用有问题就只测试工具调用的功能;把其它无关代码全部注释掉,如果确认这个环节没问题之后,再测试其它功能模块。
在智能体这种长距离调用以及复杂环境下,最忌讳的就是全流程的debug方法;原因就在于其不稳定因素太多,不可控变量也太多;这样就会导致你无法判断到底是哪个环节出了问题。
(文:AI探索时代)