Langchain-Chatchat + Grafana:构建可观察的本地化知识问答平台

在企业智能化转型浪潮中,一个日益突出的矛盾浮现出来:员工每天面对堆积如山的制度文件、技术手册和操作规范,却仍频繁询问“这个流程怎么走?”、“那个政策怎么解释?”。传统文档管理系统检索效率低、信息分散,而将敏感资料上传至公有云AI服务又面临合规风险。有没有一种方式,既能实现自然语言问答的便捷性,又能确保数据不出内网?

正是在这种现实需求驱动下,Langchain-Chatchat 逐渐成为开源社区中的热门选择。它不是一个简单的聊天机器人框架,而是一套完整的本地知识库解决方案——把企业的私有文档变成可对话的知识体。更进一步,当我们将这套系统与 Grafana 结合,为其装上“仪表盘”,就能实时看清它的每一次呼吸:哪个问题被问得最多?响应是否变慢了?向量检索有没有异常?这不再是黑盒运行的AI玩具,而是一个真正可运维、可优化的生产级系统。


整个系统的运转其实可以想象成一位精通公司所有文档的“数字专家”。你问他:“新员工试用期多久?”,他不会凭空编造答案,而是先快速翻阅人事手册中最相关的段落,再结合上下文组织语言作答。这一过程的背后,是几个关键技术环节的精密协作。

首先是文档的“消化”阶段。系统支持PDF、Word、PPT等多种格式输入,通过专用解析器提取原始文本。但直接将整篇文档喂给模型显然不现实——既超出上下文长度限制,也难以精准定位信息。因此需要进行文本分块(Text Splitting)。这里有个工程上的微妙平衡:切得太碎会丢失语义连贯性,切得太长则影响检索精度。实践中推荐使用 RecursiveCharacterTextSplitter,它会优先在段落、句子边界处分割,并设置50~100字符的重叠区域,避免关键信息被“一刀两断”。

接下来是核心的“记忆编码”过程。每个文本块会被送入一个中文优化的嵌入模型(Embedding Model),例如 ZhipuAI 的 bge-large-zh 或 MokaAI 的 m3e-base。这些模型能将语义相近的中文句子映射到向量空间中邻近的位置。比如“年假”和“带薪休假”虽然字面不同,但向量距离会很接近。编码后的向量存入本地向量数据库,如轻量级的 FAISS(适合十万级以下片段)或功能更全的 Chroma/Milvus(支持持久化和分布式)。这就相当于为这位“数字专家”建立了一套高效索引的大脑。

当用户提问时,系统同样将问题转化为向量,在向量库中寻找最相似的Top-K个知识片段,作为上下文输入给大语言模型(LLM)。这种 RAG(Retrieval-Augmented Generation) 架构巧妙地规避了纯生成模型容易“幻觉”的问题——因为答案必须基于真实文档片段生成。对于部署环境,GPU充足时可用 llama.cpp 加载 GGUF 格式的 Llama/Qwen 模型实现高速推理;若只有CPU,则推荐量化版的 ChatGLM3-6B-int4,在响应速度和准确性之间取得良好平衡。

下面这段代码浓缩了上述流程的核心逻辑:

from langchain_community.document_loaders import PyPDFLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.embeddings import HuggingFaceEmbeddings
from langchain.vectorstores import FAISS
from langchain.chains import RetrievalQA
from langchain_community.llms import HuggingFaceHub

# 1. 加载PDF文档
loader = PyPDFLoader("company_policy.pdf")
pages = loader.load_and_split()

# 2. 文本分块
text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=500,
    chunk_overlap=50
)
docs = text_splitter.split_documents(pages)

# 3. 初始化中文嵌入模型
embeddings = HuggingFaceEmbeddings(model_name="BAAI/bge-large-zh")

# 4. 构建向量数据库
db = FAISS.from_documents(docs, embeddings)

# 5. 创建检索器
retriever = db.as_retriever(search_kwargs={"k": 3})

# 6. 配置本地LLM(以HuggingFace为例)
llm = HuggingFaceHub(
    repo_id="Qwen/Qwen-7B-Chat",
    model_kwargs={"temperature": 0.7, "max_new_tokens": 512},
    huggingfacehub_api_token="your_token"
)

# 7. 构建RAG问答链
qa_chain = RetrievalQA.from_chain_type(
    llm=llm,
    chain_type="stuff",
    retriever=retriever,
    return_source_documents=True
)

# 8. 执行查询
query = "公司年假是如何规定的?"
result = qa_chain.invoke({"query": query})
print("回答:", result["result"])
print("来源页码:", [doc.metadata['page'] for doc in result['source_documents']])

值得注意的是,这套系统的设计极具弹性。你可以轻松替换其中任意组件:换一个更强的embedding模型提升召回率,改用Milvus应对更大规模知识库,或是接入不同的LLM比较生成质量。这种模块化架构让开发者不必从零造轮子,也能根据实际资源灵活调优。

然而,仅仅让系统“跑起来”还不够。一旦投入实际使用,运维人员最常遇到的问题是:“为什么最近回答变慢了?”、“是不是有人在刷接口?”、“哪些文档经常查不到?” 这些问题背后,其实是对系统可观测性的渴求。这也是为什么我们引入 Grafana 的根本原因。

要在Langchain-Chatchat中实现监控,第一步是在服务中埋点。Python生态下的 prometheus_client 库提供了简洁的接口。我们可以定义几类关键指标:

  • Counter 类型用于累计总量,如总请求数、错误数;
  • Histogram 则记录响应时间的分布情况,便于计算P95/P99延迟。

通过一个装饰器,就能无侵入地包裹核心处理函数:

from prometheus_client import start_http_server, Counter, Histogram
import time
import functools

QUERY_COUNTER = Counter('chatbot_queries_total', 'Total number of user queries')
RESPONSE_TIME = Histogram('chatbot_response_time_seconds', 'Response time for QA requests')
FAILURE_COUNTER = Counter('chatbot_errors_total', 'Total number of failed requests')

def monitor_request(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        start_time = time.time()
        try:
            QUERY_COUNTER.inc()
            result = func(*args, **kwargs)
            return result
        except Exception as e:
            FAILURE_COUNTER.inc()
            raise e
        finally:
            duration = time.time() - start_time
            RESPONSE_TIME.observe(duration)
    return wrapper

@monitor_request
def handle_question(query: str):
    time.sleep(0.5)  # 模拟处理耗时
    return {"answer": "这是一条测试回答", "source": "policy.pdf"}

# 启动指标暴露服务
start_http_server(8000)

随后配置 Prometheus 定期抓取该服务的 /metrics 接口:

scrape_configs:
  - job_name: 'langchain_chatchat'
    static_configs:
      - targets: ['host.docker.internal:8000']

一切就绪后,Grafana 就可以连接 Prometheus 数据源,创建出直观的仪表盘。典型的视图包括:

  • QPS曲线图rate(chatbot_queries_total[1m]) 展示每秒请求数趋势,帮助识别访问高峰;
  • 延迟热力图:观察响应时间的分布变化,及时发现性能劣化;
  • 错误率告警面板:一旦 rate(chatbot_errors_total[1m]) > 0 即触发视觉提醒,甚至联动邮件或企业微信通知;
  • 多维分析图表:如果在指标中添加了标签(如 knowledge_base="hr"model="qwen"),还能对比不同知识库或模型的表现差异。

这样的监控体系带来的价值远不止“看看图表”那么简单。某次线上故障排查中,团队发现整体响应时间突然上升,但LLM本身负载正常。通过细化埋点才发现,问题出在向量检索阶段——由于近期导入了一批扫描版PDF,OCR识别质量差导致文本块内容混乱,迫使系统不得不扩大检索范围,从而拖慢了速度。没有分层监控,这类问题很难快速定位。

当然,在落地过程中也有一些值得分享的经验教训:

  • 安全不可忽视:对上传文件务必做格式校验和病毒扫描,防止恶意构造的PDF触发解析漏洞;
  • 防滥用设计:限制单次查询长度、设置IP请求频率阈值,避免被当作免费算力池滥用;
  • 知识库更新策略:支持增量索引更新而非全量重建,减少服务中断时间;
  • 用户体验优化:返回结果时附带原文出处页码或段落链接,增强回答的可信度。

从架构上看,整个系统形成了清晰的层次:

+------------------+       +----------------------------+
|   用户界面       |<----->| FastAPI 后端服务           |
| (Web / API Client)|       | - 请求路由                 |
+------------------+       | - 身份认证                 |
                           | - 日志记录                 |
                           | - Prometheus 指标暴露      |
                           +-------------+--------------+
                                         |
                                         v
                    +-------------------------------------+
                    |     LangChain 核心处理引擎          |
                    |  - Document Loader                |
                    |  - Text Splitter                  |
                    |  - Embedding Model (BGE)          |
                    |  - Vector Store (FAISS/Chroma)     |
                    |  - LLM (Qwen/GLM/Llama)            |
                    +-------------------------------------+

                                         |
                                         v
                   +----------------------------------+
                   |    监控与可观测性子系统          |
                   |  - Prometheus (指标采集)         |
                   |  - Grafana (可视化仪表盘)        |
                   +----------------------------------+

各组件间通过标准协议通信,保证了系统的松耦合与可扩展性。

这套“智能+可观测”的组合拳,特别适用于金融、政务、医疗等对数据安全要求极高的场景。它不仅解决了知识获取效率低的老问题,更重要的是建立起一种可持续演进的技术范式:我们不再只是部署一个AI模型,而是构建一个能自我诊断、持续优化的智能服务体系。未来,甚至可以基于历史查询数据自动识别知识盲区,提示管理员补充文档,真正实现知识管理的闭环。

当AI系统不仅能回答问题,还能告诉我们它“为什么能回答”以及“运行得好不好”时,才真正迈出了工程化落地的关键一步。Langchain-Chatchat 与 Grafana 的结合,正是这条道路上一次务实而富有启发性的实践。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐