1. 项目概述当可观测性遇上自然语言最近在搞可观测性平台的朋友估计都遇到过类似的头疼事想查一下昨晚某个服务的延迟峰值得先在 Grafana 里找到对应的仪表盘然后回忆那个指标叫http_request_duration_seconds还是request_latency接着在 PromQL 里写查询语句过滤service标签再按quantile聚合……一套操作下来五分钟过去了问题还没定位清楚。这还只是有明确目标的情况如果是“感觉系统有点慢看看哪里有问题”这种模糊需求更是无从下手。这就是传统可观测性工具的一个典型痛点技术门槛高查询效率低。运维、SRE 甚至开发同学必须熟悉复杂的查询语法如 PromQL、LogQL、KQL和指标/日志/链路数据的存储结构才能有效利用这些数据。而Horizon UI · AI Assistant的出现正是为了解决这个核心矛盾。它本质上是一个“翻译官”架设在你的可观测性数据如 Prometheus、Loki、Tempo、Elasticsearch 等之上允许你直接用“人话”——也就是自然语言——来提问然后由 AI 理解你的意图自动生成对应的查询语句执行并返回结果。举个例子你不用再写rate(node_cpu_seconds_total{mode“idle”}[5m])而是直接问“过去一小时服务器的平均 CPU 使用率是多少” 或者更复杂的“帮我找出今天上午 10 点到 11 点之间响应时间超过 500 毫秒的所有 API 端点并按服务名称分组。” 这种交互方式的变革极大地降低了可观测性数据的消费门槛让更多角色如产品经理、业务负责人也能参与到系统健康度的讨论中真正让数据“可观测”变得“可对话”。这个项目的核心价值不在于替代 Grafana、Kibana 这些成熟的 UI而在于提供一种全新的、更人性化的数据访问入口。它尤其适合以下场景日常巡检与故障排查、向非技术角色汇报系统状态、快速验证一个临时性的数据猜想或者在紧急故障时让工程师能跳过语法细节直击问题核心。2. 核心架构与工作原理拆解要理解 Horizon UI · AI Assistant 是如何工作的我们需要把它拆解成几个核心组件。它不是一个魔法黑盒而是一个精心设计的、由多个模块协同工作的系统。2.1 整体架构从自然语言到数据图表一个典型的 AI Assistant for Observability 架构通常包含以下层次交互层前端/UI用户输入自然语言问题的界面。这可以是一个独立的 Web 应用也可以是嵌入到现有 Grafana 或内部运维平台的一个聊天窗口。关键是要提供清晰、流畅的对话体验。自然语言理解层NLU这是大脑。它接收用户的问题理解其意图。目前主流方案基于大语言模型LLM如 GPT-4、Claude 3 或开源的 Llama 3、Qwen 等。这一层需要完成两项核心任务意图识别判断用户想干什么是查询指标、搜索日志、追踪链路还是对比数据实体抽取从问题中提取关键参数如时间范围“过去5分钟”、“今天”、服务名称“user-service”、“payment-gateway”、指标名称“错误率”、“吞吐量”、阈值“超过 1 秒”、“低于 99.9%”等。查询生成与优化层这是翻译器。NLU 层输出的结构化意图和参数会被送到这一层转换成后端数据源能理解的具体查询语言。例如识别到查询“CPU使用率”且数据源是 Prometheus则生成100 - (avg by (instance) (rate(node_cpu_seconds_total{mode“idle”}[5m])) * 100)。识别到搜索“登录失败”的日志且数据源是 Loki则生成{job~“auth-service.*”} | “login” | “fail”。这一层还需要处理模糊匹配。比如用户说“看看网关的流量”模型需要知道“网关”可能对应ingress-nginx或api-gateway服务并尝试生成包含这些标签的查询。数据源连接与执行层这是执行者。它负责连接真实的可观测性后端如 Prometheus、Loki、Tempo、Elasticsearch、Jaeger 等执行生成的查询语句并获取原始数据。结果解释与呈现层这是表达者。原始数据通常是数字、文本或 JSON对用户不友好。这一层需要将数据“翻译”回自然语言并结合图表进行可视化。例如返回“过去5分钟user-service的平均延迟为 145ms在正常范围内”并附上一个折线图。Horizon UI · AI Assistant 需要将这五层无缝衔接形成一个闭环。其中第2层和第3层是技术难点和价值核心直接决定了助理的“智商”和实用性。2.2 关键技术选型为什么是 RAG LLM单纯用一个通用大模型如 ChatGPT来回答运维问题是不行的因为它不了解你公司内部特有的服务名、指标体系和数据结构。因此业界普遍采用RAG检索增强生成架构来构建这类场景的 AI 应用。RAG 的核心思想是“先检索后生成”。具体到我们的场景知识库构建首先我们需要为 AI 助理建立一个专属的“运维知识库”。这个知识库不是文档而是你系统中所有可观测性数据的元数据Metadata和模式Schema。例如从 Prometheus 拉取所有可用的指标名称metric_names及其标签键值对。从服务注册中心如 Consul, K8s Service获取所有运行中的服务列表。整理关键业务指标的定义文档如“业务成功率 1 - (5xx 请求数 / 总请求数)”。将 Grafana 仪表盘的 JSON 定义作为上下文让 AI 知道有哪些现成的视图。检索当用户提问时系统首先将问题转换成向量在知识库中进行语义搜索找出最相关的元数据片段。比如用户问“订单服务的错误情况”系统会检索出与“order-service”、“error”、“4xx”、“5xx”相关的指标和标签。增强提示Prompt将检索到的相关元数据作为上下文Context和系统指令System Prompt的一部分一起提交给 LLM。此时的 Prompt 可能长这样你是一个运维 AI 助手。请根据以下系统信息和用户问题生成对应的 Prometheus 查询语句。 系统指标列表[http_requests_total,http_request_duration_seconds,container_cpu_usage_seconds_total...] 服务列表[order-service,payment-service,inventory-service...] 用户问题今天订单服务的平均响应时间是多少生成LLM 在有了具体上下文后就能生成准确、可执行的查询语句avg_over_time(http_request_duration_seconds_sum{service“order-service”}[24h]) / avg_over_time(http_request_duration_seconds_count{service“order-service”}[24h])。为什么选择这个方案准确性高避免了 LLM 的“幻觉”生成的查询基于真实的系统元数据。成本可控不需要为每个垂直领域微调模型利用通用 LLM 的理解能力即可。更新方便系统扩容、指标变更时只需更新知识库无需重新训练模型。可解释性强可以追溯是哪些元数据影响了本次查询生成。注意知识库的构建和维护是持续性的工作。建议设计一个定时任务定期从各数据源同步元数据确保 AI 助理的知识是最新的。初次搭建时也可以考虑从现有的 Grafana 仪表盘和告警规则中反向提取指标使用模式作为高质量的初始知识。3. 核心实现细节与实操要点理解了架构我们来看看如何一步步实现一个可用的 AI 助理。这里我们以一个基于开源栈的方案为例进行拆解你可以根据自身技术栈进行调整。3.1 环境与工具准备我们假设后端可观测性栈是经典的Prometheus Loki GrafanaAI 部分使用LangChain OpenAI GPT-4 API Chroma向量数据库。这是一个兼顾效果和开发效率的组合。1. 后端数据源确认Prometheus: 用于指标查询地址http://prometheus:9090Loki: 用于日志查询地址http://loki:3100确保这些服务有稳定的网络连接并且 API 可访问。2. AI 与框架选型LangChain 它是构建 LLM 应用的“脚手架”提供了连接各种组件模型、向量库、工具链的标准接口能极大简化开发。我们用它来编排 RAG 流程。OpenAI GPT-4 API 选择它是因为在代码生成和理解复杂指令方面表现稳定。你也可以替换为 Anthropic Claude、Azure OpenAI 或本地部署的 Llama 3需考虑性能。Chroma 轻量级、易用的开源向量数据库用于存储和检索我们的元数据知识库。生产环境可以考虑 Weaviate 或 Pinecone。编程语言 Python 是 LangChain 生态的首选。安装核心依赖pip install langchain langchain-openai chromadb requests pandas # 如果需要与Grafana API交互安装 grafana-api pip install grafana-api3.2 构建运维知识库核心步骤这是最关键的步骤知识库的质量直接决定 AI 助理的智商。步骤一采集元数据我们需要编写脚本从各个源头收集信息。import requests import json import pandas as pd from langchain.schema import Document from langchain.embeddings import OpenAIEmbeddings from langchain.vectorstores import Chroma class MetadataCollector: def __init__(self, prometheus_url, loki_url): self.prometheus_url prometheus_url self.loki_url loki_url def fetch_prometheus_metrics(self): 从Prometheus API获取所有指标名称和标签 try: # 获取指标列表 response requests.get(f{self.prometheus_url}/api/v1/label/__name__/values) metric_names response.json()[data] metrics_metadata [] for metric in metric_names[:100]: # 示例只取前100实际应分批处理 # 获取该指标的一个样本以了解标签结构 query f{{__name__{metric}}} resp requests.get(f{self.prometheus_url}/api/v1/query, params{query: query}) data resp.json() if data[data][result]: sample data[data][result][0] labels sample[metric] description f指标名: {metric}, 示例标签: {labels} metrics_metadata.append(description) return metrics_metadata except Exception as e: print(f获取Prometheus指标失败: {e}) return [] def fetch_services_from_k8s(self): 假设从K8s API获取服务列表简化示例 # 实际中可使用 kubernetes python client services [order-service, payment-service, user-service, inventory-service, api-gateway] return [f服务名称: {svc} for svc in services] def fetch_grafana_dashboards(self, grafana_url, api_key): 从Grafana获取仪表盘信息作为上下文 headers {Authorization: fBearer {api_key}} resp requests.get(f{grafana_url}/api/search, headersheaders) dashboards resp.json() dashboard_info [] for db in dashboards: # 获取每个仪表盘的详情包含面板的查询语句 db_detail requests.get(f{grafana_url}/api/dashboards/uid/{db[uid]}, headersheaders).json() # 提取标题和包含的数据源、查询类型信息 info f仪表盘 {db[title]} 包含关于 {db_detail[dashboard].get(tags, [])} 的可视化。 dashboard_info.append(info) return dashboard_info # 使用示例 collector MetadataCollector(http://localhost:9090, http://localhost:3100) metrics collector.fetch_prometheus_metrics() services collector.fetch_services_from_k8s() # dashboards collector.fetch_grafana_dashboards(http://localhost:3000, your-api-key) all_metadata metrics services # dashboards print(f共收集到 {len(all_metadata)} 条元数据)步骤二向量化存储将收集到的文本元数据转换成向量存入 Chroma。def create_vector_store(metadata_list): 创建向量存储 # 将元数据列表转换成LangChain的Document对象 docs [Document(page_contenttext) for text in metadata_list] # 使用OpenAI的嵌入模型也可用其他开源模型 embeddings OpenAIEmbeddings(openai_api_keyyour-openai-key) # 创建并持久化向量存储 vector_store Chroma.from_documents( documentsdocs, embeddingembeddings, persist_directory./chroma_db # 指定持久化目录 ) vector_store.persist() return vector_store # 执行创建 vector_store create_vector_store(all_metadata) print(知识库向量存储创建完成。)实操心得元数据的描述文本page_content非常关键。不要只存一个指标名http_requests_total而要存“指标名: http_requests_total, 类型: 计数器, 含义: HTTP请求总数, 常见标签: service, method, path, code”。丰富的描述能极大提升检索的准确性。可以考虑从 Prometheus 的HELP文本中提取描述。3.3 设计智能体Agent与工具链AI 助理不是一个简单的问答机器人而是一个能够根据目标自主选择“工具”即查询不同数据源的能力的智能体。LangChain 的 Agent 框架非常适合这个场景。定义工具Tools 每个工具对应一种数据查询能力。from langchain.agents import Tool from langchain.utilities import WikipediaAPIWrapper import requests import time class PrometheusQueryTool: Prometheus查询工具 def __init__(self, prometheus_url): self.url prometheus_url def run(self, query: str) - str: 执行PromQL查询 try: # 这里接收的是AI生成的PromQL不是自然语言 response requests.get(f{self.url}/api/v1/query, params{query: query, time: time.time()}) data response.json() if data[status] success: results data[data][result] if not results: return 查询成功但未匹配到数据。 # 简化返回实际可以格式化得更好看 return f查询到 {len(results)} 条结果。示例{results[0]} else: return f查询失败{data.get(error, Unknown error)} except Exception as e: return f请求异常{str(e)} class ObservabilityAgent: def __init__(self, vector_store, prometheus_tool, openai_api_key): self.vector_store vector_store self.prometheus_tool prometheus_tool # 初始化LLM from langchain.chat_models import ChatOpenAI self.llm ChatOpenAI(modelgpt-4, temperature0, openai_api_keyopenai_api_key) # 定义工具列表 self.tools [ Tool( namePrometheus指标查询, funcself.prometheus_tool.run, description用于查询时序指标数据。输入必须是有效的PromQL查询语句。 ), # 未来可以继续添加 Loki日志查询、Tempo链路查询等工具 # Tool(nameLoki日志搜索, funcloki_tool.run, description用于搜索日志数据。输入必须是有效的LogQL语句。), ] def retrieve_context(self, question): 从知识库中检索相关上下文 retriever self.vector_store.as_retriever(search_kwargs{k: 5}) # 返回最相关的5条 docs retriever.get_relevant_documents(question) context \n.join([doc.page_content for doc in docs]) return context def generate_response(self, user_question): 核心处理流程检索 - 生成提示 - 调用LLM - 执行工具 - 回复 # 1. 检索上下文 context self.retrieve_context(user_question) print(f检索到的上下文:\n{context}\n) # 2. 构建系统提示词System Prompt这是指导AI行为的关键 system_prompt f你是一个专业的运维AI助手负责将用户关于系统监控的问题转换成具体的查询命令。 你拥有以下系统知识作为参考 {context} 请严格遵循以下步骤 1. 理解用户问题。 2. 根据上述知识判断用户需要查询哪种数据指标、日志、链路。 3. **如果问题涉及指标查询**请生成精确的PromQL语句。确保使用知识库中存在的指标名和标签。 4. 你的输出**必须且只能**是纯PromQL语句不要有任何额外的解释、标记或格式。 5. 如果无法从知识库中确定如何查询或问题不清晰请输出“ERROR: 无法生成查询请提供更明确的信息或检查指标是否存在。” 用户问题{user_question} 生成的PromQL # 3. 调用LLM生成查询 try: response self.llm.predict(system_prompt) print(fAI生成的查询语句: {response}) # 4. 检查是否是错误信息或真正的查询 if response.startswith(ERROR): return response else: # 5. 执行查询工具 query_result self.prometheus_tool.run(response) # 6. 将结果再次交给LLM转换成自然语言回复可选可在此处添加格式化 final_prompt f将以下查询结果用简洁、友好的自然语言总结给用户\n查询语句{response}\n查询结果{query_result} final_response self.llm.predict(final_prompt) return final_response except Exception as e: return f处理过程中发生错误{str(e)} # 初始化并运行 prom_tool PrometheusQueryTool(http://localhost:9090) agent ObservabilityAgent(vector_store, prom_tool, your-openai-key) user_question 今天订单服务的请求错误率是多少 answer agent.generate_response(user_question) print(f助理回答\n{answer})这个ObservabilityAgent类实现了一个简化的流程。在实际项目中你需要使用 LangChain 更强大的AgentExecutor和initialize_agent来管理工具的选择和调用顺序让 AI 自己决定何时使用哪个工具。4. 前端交互界面与用户体验设计一个强大的后端需要一个易用的前端。对于 AI 助理聊天界面是最自然的形式。这里我们可以用一个简单的 Web 应用如使用 Streamlit 或 Gradio 快速搭建来演示。使用 Streamlit 快速构建界面# app.py import streamlit as st from your_agent_module import ObservabilityAgent, PrometheusQueryTool, create_vector_store import pandas as pd # 页面配置 st.set_page_config(page_title运维AI助理, page_icon, layoutwide) st.title( Horizon UI · AI 运维助理) st.markdown(用日常语言查询你的 Prometheus、Loki 数据。) # 侧边栏初始化模拟 with st.sidebar: st.header(配置) openai_key st.text_input(OpenAI API Key, typepassword) prometheus_url st.text_input(Prometheus 地址, valuehttp://localhost:9090) if st.button(初始化助理): if openai_key and prometheus_url: # 这里应加入加载知识库的逻辑 with st.spinner(加载知识库中...): # 假设知识库已预先建好这里加载 # vector_store Chroma(persist_directory./chroma_db, embedding_functionembeddings) # prom_tool PrometheusQueryTool(prometheus_url) # st.session_state.agent ObservabilityAgent(vector_store, prom_tool, openai_key) st.success(助理初始化成功) else: st.error(请填写必要的API Key和地址。) # 主聊天区域 if messages not in st.session_state: st.session_state.messages [] # 显示历史消息 for message in st.session_state.messages: with st.chat_message(message[role]): st.markdown(message[content]) # 聊天输入 if prompt : st.chat_input(输入你的问题例如过去一小时CPU使用率趋势如何): # 添加用户消息 st.session_state.messages.append({role: user, content: prompt}) with st.chat_message(user): st.markdown(prompt) # 生成助理回复 with st.chat_message(assistant): with st.spinner(思考中...): # 这里调用之前定义的 agent.generate_response # 为了演示我们模拟一个回复 if agent in st.session_state: response st.session_state.agent.generate_response(prompt) else: response ⚠️ 请先在侧边栏初始化AI助理。 st.markdown(response) st.session_state.messages.append({role: assistant, content: response})这个简单的界面已经具备了核心功能。生产级应用需要考虑更多对话历史保存上下文支持多轮对话如“对比一下昨天的情况”。结果可视化不仅返回文字还应直接渲染图表。可以集成 Grafana 的渲染 API或者使用 Plotly、Matplotlib 根据返回数据动态生成。查询确认在执行可能耗时较长或范围较大的查询前让用户确认生成的查询语句。反馈机制提供“结果是否有用”的反馈按钮用于后续优化模型。5. 安全、成本与性能优化考量将 AI 引入运维领域除了功能还必须严肃考虑安全、成本和性能。1. 安全与权限控制查询隔离AI 助理生成的查询必须在严格的权限沙箱中执行。绝不能让其拥有直接读写数据库或执行系统命令的能力。应通过一个具有最小必要权限的专用服务账户来连接 Prometheus/Loki。输入过滤与审计对所有用户输入进行基本的过滤防止 Prompt 注入攻击。同时记录所有用户问题、生成的查询语句和执行结果用于审计和模型优化。数据脱敏确保 AI 助理返回的结果中不包含敏感信息如 IP、密钥、个人信息。可以在结果处理层添加过滤规则。API 密钥管理OpenAI 等服务的 API Key 必须妥善保管使用环境变量或密钥管理服务切勿硬编码在前端。2. 成本控制LLM API 调用成本GPT-4 等模型费用不菲。优化策略包括缓存对相同或相似的问题缓存生成的查询语句和结果。例如将“CPU使用率”和“CPU利用率”映射到同一个 PromQL。使用更经济的模型对于简单的意图识别可以使用 GPT-3.5-Turbo仅在需要复杂逻辑和代码生成时使用 GPT-4。精简 Prompt优化系统提示词减少不必要的 token 消耗。知识库的检索结果也要做摘要和去重。设置用量限额为用户或团队设置每日/每月的查询次数上限。查询执行成本一个模糊的“看看系统状态”可能被翻译成多个重型查询拖垮监控后端。查询超时与限制为 AI 发起的查询设置严格的超时时间如 10 秒和数据点数量限制。查询优化在生成查询时优先使用录制规则Recording Rules或预聚合的指标避免全量扫描。3. 性能优化知识库检索速度向量检索的速度直接影响响应时间。确保 Chroma 数据库有合适的索引或考虑使用性能更高的商业向量数据库。异步处理对于长耗时查询可以改为异步模式。即 AI 立即返回“正在查询请稍后查看结果”然后在后台执行查询并通过 WebSocket 或轮询通知用户。LLM 响应速度选择低延迟的模型或 API 端点。对于内部部署可以考虑量化后的开源模型如 Llama 3 的量化版虽然效果可能略逊但延迟和成本极低。注意事项在项目初期强烈建议建立一个“安全沙盒”环境进行测试。在这个环境中使用生产数据的副本让 AI 助理自由运行观察其生成的查询是否会引发性能问题或安全风险并不断完善你的提示词和防护规则。6. 评估、迭代与未来展望如何判断你的 AI 助理是否合格不能只靠感觉需要建立评估体系。1. 核心评估指标查询生成准确率随机抽取一批历史运维问题或构造一批让 AI 生成查询由专家判断查询是否正确。目标应达到 85% 以上。查询执行成功率生成的查询语句在数据源中能成功执行的比例。语法错误或引用不存在的指标会导致失败。用户满意度在界面中设置简单的反馈按钮/收集主观评价。平均解决时间对比使用 AI 助理前后处理一个典型运维问题如定位延迟毛刺所需的时间。2. 持续迭代流程AI 助理不是一次开发完就结束的项目而需要持续运营。收集错误案例建立一个渠道如反馈按钮、内部群鼓励用户上报“AI 答非所问”或“查询错误”的情况。分析错误根因错误通常源于1) 知识库缺失元数据2) Prompt 设计有歧义3) LLM 本身的理解偏差。针对性优化补充知识库将新上线的服务、新定义的指标及时纳入。优化 Prompt针对某一类高频错误调整系统提示词。例如如果 AI 总混淆“错误率”和“错误数”就在 Prompt 中明确两者的计算公式。引入 Few-Shot Learning在 Prompt 中提供几个“问题-正确查询”的示例能显著提升模型在特定模式下的表现。定期重训练/更新随着系统架构变化定期如每月更新知识库向量存储。3. 可能的进阶方向当基础问答稳定后可以考虑增强功能主动洞察与告警不局限于问答让 AI 定时分析指标主动发现异常模式并生成报告。例如“过去24小时payment-service的 P99 延迟有上升趋势建议关注。”根因分析RCA辅助在发生告警时AI 可以自动关联同一时间的指标、日志和链路数据生成一份初步的根因分析报告列出可能受影响的服务和异常指标。与运维流程集成将 AI 助理与 ITSM如 Jira、告警平台如 Alertmanager集成。收到告警后自动创建故障单并附上 AI 生成的初步分析。多模态交互支持用户上传截图如模糊的图表AI 尝试解读图中的数据并回答相关问题。构建 Horizon UI · AI Assistant 是一个典型的“AI 赋能传统工具”的过程。它不会一夜之间取代所有现有的监控面板但它通过降低数据访问的门槛让可观测性数据从“专家的工具”变成了“团队的语言”。从简单的自然语言查询开始逐步迭代你会发现它正在悄然改变团队排查问题、理解系统的方式。启动这个项目最好的时间一个是去年另一个就是现在。从一个小的、明确的数据源比如先只接 Prometheus开始收集最初的 100 个问题-查询对不断优化你的 Prompt 和知识库你会很快看到一个能真正帮上忙的“智能同事”诞生。