基于LangGraph构建可控制日志分析系统:子图组合与状态管理详解
在现代AI应用开发中,日志分析和故障处理是保证系统稳定运行的重要环节。本文将详细介绍如何使用LangGraph框架构建一个可控制的日志分析系统,该系统能够自动分析日志、识别故障并生成报告。系统采用模块化设计,通过多个子图的组合实现复杂的业务逻辑。
系统整体架构
本文介绍的日志分析系统采用三层图结构设计:
- 故障分析子图(Failure Analysis):负责识别和分析失败的日志记录
- 问题总结子图(Question Summarization):负责生成问题摘要和报告
- 主入口图(Entry Graph):协调各个子图的执行流程
数据结构定义
日志数据结构
首先,我们定义了日志的基本数据结构:
from typing import TypedDict, Annotated, Optional, List, Dict, Any, get_type_hints
from operator import add
from langgraph.graph import StateGraph, START, END
class Logs(TypedDict):
id: str # 日志的唯一标识符
question: str # 问题文本
docs: Optional[List] # 可选的相关文档列表
answer: str # 回答文本
grade: Optional[int] # 可选的评分
grader: Optional[str] # 可选的评分者
feedback: Optional[str] # 可选的反馈信息
这个数据结构包含了日志分析所需的所有关键信息:
id
:用于唯一标识每条日志记录question
和answer
:记录问答对信息grade
、grader
、feedback
:用于质量评估和反馈
故障分析子图
状态定义
class FailureAnalysisState(TypedDict):
docs: List[Logs]
failures: List[Logs]
fa_summary: str
核心功能实现
故障分析子图包含两个主要节点:
1. 获取失败日志
def get_failures(state):
doce = state['docs']
failures = [doc for doc in doce if "grade" in doc]
return {"failures": failures}
这个函数通过检查日志中是否存在grade
字段来识别失败的记录。在实际应用中,可能需要根据具体的业务逻辑调整失败识别条件。
2. 生成故障摘要
def generate_summary(state):
failures = state["failures"]
# 在实际应用中,这里会调用LLM进行智能分析
fa_summary = "错误信息分析结果"
return {"fa_summary": fa_summary}
子图构建
fa_builder = StateGraph(FailureAnalysisState)
fa_builder.add_node("get_failures", get_failures)
fa_builder.add_node("generate_summary", generate_summary)
fa_builder.add_edge(START, "get_failures")
fa_builder.add_edge("get_failures", "generate_summary")
fa_builder.add_edge("generate_summary", END)
问题总结子图
状态定义
class QuestionSummarizationState(TypedDict):
docs: List[Logs] # 日志列表
qs_summary: str # 问题总结
report: str # 报告
功能模块
问题总结子图包含三个处理节点:
1. 生成问题总结
def generate_summary(state):
docs = state["docs"]
# 实际应用中会调用summarize函数进行智能总结
summary = "问题汇总"
return {"qs_summary": summary}
2. 发送到Slack
def send_to_slack(state):
qs_summary = state["qs_summary"]
# 实际应用中会调用report_generation函数
report = "foo bar baz"
return {"report": report}
3. 格式化报告
def format_report_for_slack(state):
report = state["report"]
# 实际应用中会调用report_format函数
formatted_report = "固定的格式化报告内容"
return {"report": formatted_report}
子图构建
qs_builder = StateGraph(QuestionSummarizationState)
qs_builder.add_node("generate_summary", generate_summary)
qs_builder.add_node("send_to_slack", send_to_slack)
qs_builder.add_node("format_report_for_slack", format_report_for_slack)
qs_builder.add_edge(START, "generate_summary")
qs_builder.add_edge("generate_summary", "send_to_slack")
qs_builder.add_edge("send_to_slack", "format_report_for_slack")
qs_builder.add_edge("format_report_for_slack", END)
主入口图
状态定义
主入口图的状态设计使用了Annotated
类型注解,支持状态合并:
class EntryGraphState(TypedDict):
raw_logs: Annotated[List[Dict], add]
docs: Annotated[List[Logs], add]
fa_summary: str
report: str
使用add
操作符意味着在状态更新时,列表类型的字段会进行合并操作。
数据转换
def convert_logs_to_docs(state):
raw_logs = state["raw_logs"]
docs = raw_logs
return {"docs": docs}
这个函数负责将原始日志数据转换为标准的Logs
格式。
主图构建
entry_builder = StateGraph(EntryGraphState)
entry_builder.add_node("convert_logs_to_docs", convert_logs_to_docs)
entry_builder.add_node("question_summarization", qs_builder.compile())
entry_builder.add_node("failure_analysis", fa_builder.compile())
entry_builder.add_edge(START, "convert_logs_to_docs")
entry_builder.add_edge("convert_logs_to_docs", "question_summarization")
entry_builder.add_edge("convert_logs_to_docs", "failure_analysis")
entry_builder.add_edge("question_summarization", END)
entry_builder.add_edge("failure_analysis", END)
系统执行与测试
测试数据
raw_logs = [{
"id": "1",
"question": "如何导入ChatOpenAI?",
"answer": "要导入ChatOpenAI, 使用: 'from langchain_openai import ChatOpenAI.'",
}, {
"id": "2",
"question": "如何使用Chroma向量存储?",
"answer": "要使用Chroma,请定义: rag_chain = create_retrieval_chain(retriever, question_answer_chain).",
"grade": 0,
"grader": "文档相似性回顾",
"feedback": "检索到的文档一般讨论了向量存储,但没有专门讨论Chroma",
}]
系统执行
app = entry_builder.compile()
result = app.invoke({"raw_logs": raw_logs}, debug=False)
print(result)
可视化
系统还支持生成流程图,便于理解和调试:
graph_png = app.get_graph(xray=1).draw_mermaid_png()
with open("子图可控性.png", "wb") as f:
f.write(graph_png)
设计优势
1. 模块化设计
每个子图都有独立的状态和功能,便于维护和扩展。
2. 并行处理
故障分析和问题总结可以并行执行,提高系统效率。
3. 状态管理
通过Annotated
和add
操作符实现智能的状态合并机制。
4. 可扩展性
可以轻松添加新的子图或修改现有流程,不影响其他模块。
实际应用建议
1. 集成LLM
在实际部署时,应该将示例中的固定字符串替换为真实的LLM调用,实现智能分析。
2. 错误处理
添加异常处理机制,确保系统在遇到错误时能够优雅处理。
3. 监控和日志
增加系统运行监控和详细的执行日志,便于问题排查。
4. 性能优化
对于大量日志的处理,可以考虑批处理和异步执行。
总结
本文介绍的基于LangGraph的日志分析系统展示了如何通过子图组合实现复杂的业务逻辑。系统具有良好的模块化设计、并行处理能力和可扩展性,为构建AI驱动的智能运维系统提供了有效的解决方案。通过合理的状态管理和流程控制,可以轻松应对各种复杂的日志分析需求。