Agent开发应知应会(Langfuse):Langfuse Session概念详解和实战应用

0 阅读4分钟

最近在做一个 Text-to-SQL 的 Agent 项目 EasySQL,这篇文章就把我langfuse的session使用整理一下,代码都是从项目里直接搬的,欢迎大佬们高抬贵手点点star,共建、交流。

Langfuse官方文档的原文定义

Many interactions with LLM applications span multiple traces and observations. Sessions in Langfuse are a special way to group these observations across traces together and see a simple session replay of the entire interaction. Optionally, traces can be grouped into sessions. Sessions are used to group traces that are part of the same user interaction. A common example is a thread in a chat interface.

翻译一下:一次用户与 LLM 应用的交互往往不只一个请求。比如用户在聊天界面中连续问了 3 个问题,每个问题是一个独立的 Trace(一次完整的 LLM调用链路),但它们属于同一次会话。Session 就是把这些相关的 Trace 归到一组。

Session
session_id 格式任意 US-ASCII 字符串,小于 200 字符
归组逻辑所有携带相同 session_id 的 Trace 自动归入同一个 Session
创建时机无需显式创建 Session 对象,第一个携带该 session_id 的 Trace 出现时自动创建
Trace 的关系一个 Session 包含多个 Trace,一个 Trace 只属于一个 Session

项目举例

image.png

没有Session时:这两个Trace(一个会话中的两个问答) 在Langfuse Dashboard中是散落的,你不知道它们之间有关联。有Session时:点进某个Session,能看到完整的多次对话回放——用户从第1个问题到第3个问题的完整链路。

无session的情况下,所有的trace都集中展示无法筛选

image.png

有session的情况,可以根据session展示,我这里就可以通过同个session来观察第二个问题有没有取得第一个问题的历史对话上下文,由此来判断代码中的处理是否合理

image.png

也可以在Dashboards中筛选

image.png

代码实现

核心代码在 query_service.py。也就是创建一个会话session id的地方,由于项目中已经设置了session id来区分不同的会话,所以这里可以直接复用,保证langfuse中的session id和数据库中的会话session id一致。这样做的好处是:当在 Langfuse Dashboard 中看到某个Session 有问题时,可以直接用这个 ID 去业务数据库中查对应的会话记录,两边的 ID 是一致的。(这也是我认为最重要的一点)

  def _make_config(self, session_id: str, thread_id: str | None = None) -> RunnableConfig:
      effective_thread_id = thread_id or session_id
      config: RunnableConfig = {"configurable": {"thread_id": effective_thread_id}}
      if self.callbacks:
          config["callbacks"] = self.callbacks
          config["metadata"] = {                          # ← 关键
              "langfuse_session_id": session_id,          # ← Session 隔离
              "langfuse_tags": ["text2sql"],              # ← 标签
          }
          logger.debug(f"LangFuse callbacks attached: {len(self.callbacks)} handler(s)")
      return config
    async for chunk in self.graph.astream(
        input_state,
        self._make_config(session.session_id, effective_thread_id),
        stream_mode=["updates", "custom"],
    ):

工作原理

这里用的是 Langfuse 官方推荐的 metadata 传参方式。官方文档原文:

With the Python SDK, you can set trace attributes dynamically via metadata fields in chain invocation by passing a config dictionary.This is the simplest approach for adding trace context to your LangChain executions without additional setup.

官方示例:

 response = chain.invoke(
      {"topic": "cats"},
      config={
          "callbacks": [langfuse_handler],
          "metadata": {
              "langfuse_user_id": "random-user",
              "langfuse_session_id": "random-session",     
              "langfuse_tags": ["random-tag-1", "random-tag-2"] 
          }
      }
  )

Session带来的监控意义

Session 级别的聚合分析
每个 Session 的 Trace 数量用户平均问几轮才完成任务** 轮次多 = 可能需要优化追问体验**
每个 Session 的 总 Token一次完整交互的总消耗评估单次用户交互的成本
每个 Session 的 总延迟用户完成任务的总等待时间评估端到端的用户体验
每个 Session 的 失败 Trace 比例多轮中有几轮出错定位哪些类型的追问容易失败
对比没有session
场景没有 Session有 Session
查看某用户的完整交互需要自己按时间排序、手动关联直接点进 Session 看回放
统计"用户平均几轮完成任务"无法统计Dashboard 直接提供
分析"追问时 SQL 质量是否下降"需要导出数据写脚本按 Session 内的 Trace 顺序直接对比
定位"用户反馈体验差"的问题只能逐条 Trace 查看拿到 session_id 直接看全过程

总结

session是一个很小的知识点,但是使用的好对我们整个agent开发带来的增益是巨大。

以上所有代码示例均来自我的开源项目 EasySQL —— 一个 Text-to-SQL 智能体分析应用,项目地址:github.com/zaizaizhao/…。项目主要技术栈包括:

  • LangGraph:构建多步骤 Agent 状态机,支持条件路由、Human-in-the-Loop 澄清、SQL 生成→验证→修复的迭代循环
  • LangChain:LLM 调用抽象与 RunnableConfig 配置传递
  • Langfuse:Callback + 手动 Span 双模式可观测性,实现全链路追踪与业务汇总
  • PostgreSQL + AsyncPostgresSaver:LangGraph Checkpointer 状态持久化,支持多轮对话上下文
  • FastAPI + Uvicorn:异步 API 服务层,提供流式 SSE 响应
  • Milvus:向量数据库,用于 Schema 语义检索
  • Neo4j: 图数据库,用于知识图谱构建
  • Pydantic Settings:类型安全的配置管理,支持环境变量覆盖

项目示例

image.png

image.png

image.png

欢迎 Star ⭐ 和交流、共建!