目錄

AI 智慧監控:LangChain Agent 實現自然語言查詢 Prometheus (II)

前一篇文章中,我們了解了如何將 LangChain Agent 與 Prometheus 結合,以實現自然語言查詢功能。然而,這只是開始。Day 2 的挑戰在於提升系統的靈活性和功能,特別是針對自定義的 metrics,這些指標可能一開始並未包含在模型的訓練資料中。因此,我們需要通過檢索增強生成(RAG)技術,來將外部文件整合進系統,從而提升 Agent 的能力。

此外,使用 Streamlit 建立 WebUI 可以增強用戶與系統的互動性,使操作體驗更加直觀和完善。同時,監控 LangChain 中 LLM 使用的 prompt 及其花費也是至關重要的,這樣我們可以確保系統的運行並及時調整使用的策略。

因此,本篇文章將在前一篇的基礎上,探討如何進一步完善這套系統,使我們的系統更加全面,為用戶提供更精確和有效的自然語言查詢功能。

加強 LangChain Agent

RAG & Embedding Model

首先,我們先來簡單介紹一下什麼是 RAG, Embedding 以及 Chroma:

  1. 檢索增強生成 — Retrieval Augmented Generation (RAG):是一種架構解決方案,通過結合訊息檢索和生成模型,RAG 提供了一種有效的方法來提升 LLM 的回應品質。它允許模型訪問外部資源,以生成更為精確和相關的回應。
  2. Embedding Model:Embedding 是一種將文件或其他類型的原始數據轉換為數字向量的技術,以便 AI 或機器學習演算法能夠處理這些數據。而 Embedding Model 就是把原始數據轉換成 Embedding 的過程。
  3. Chroma:輕量級開源的向量資料庫,專門處理 Embedding 的儲存、取用、查詢及檢索等。

如果上述的初步介紹還是不清楚在做什麼,那我們試試看透過實作來理解。

前置作業

安裝需要的 python package

1
2
3
pip install "unstructured[md]"
pip install langchain-text-splitters
pip install langchain-chroma

準備文件

  • 這邊透過 ssl_exporter 來做舉例,在原始訓練資料中,並不會有 ssl exporter 的 metrics 資料。我們先來看看直接詢問的結果:

    /images/monitoring/agent_error_result.png
    LangChain Agent 執行結果

  • 準備一份查詢憑證剩餘天數的相關文件 ssl_exporter.md ,文件內容除了 PromQL 說明,也包含一些推理的部分

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    
    # SSL Certificate QA System Instructions
    
    ## SSL 查詢
    
    當收到詢問域名的 SSL 憑證剩餘天數的問題時,請按照以下步驟操作:
    
    1. **檢查並補全 URL**    - 檢查域名是否為完整的 URL,需要包含 `https` 安全協定和 `443` 端口。
        - 如果 URL 不完整,請補全,使其格式為 `https://<domain>:443`    - 例如,將 `www.example.com` 補全為 `https://www.example.com:443`
    2. **生成 PromQL 查詢**    - 使用第一步中補全的完整 URL 作為 `instance` 的參數。
        - 返回如下的 PromQL 查詢語句:
          ```promql
          floor((ssl_cert_not_after{instance="<complete_url>"} - time())/24/60/60)
          ```
    
注意
記得需要在環境中安裝 ssl_exporter,且確定 prometheus 有取得到 metrics 喔

載入 Markdown 文件

Langchain 提供了非常多種文件載入器,包含 Word, PDF, csv, Markdown 或 Youtube 等,這裡我們使用 Markdown 來做範例

1
2
3
4
5
6
from langchain_community.document_loaders import TextLoader

markdown_path = "./docs/ssl_exporter.md"
loader = TextLoader(markdown_path)
documents = loader.load()
combined_text = "\n".join([doc.page_content for doc in documents])  # 將 Markdown 文件內容合併為一個字串

依照 Header 來拆分 Markdown 文件

Splitter 會將文件或文字分割成一個個 chunk,用來預防文件的資訊超過 LLM 的 tokens 上限,而 Markdown 是透過 header 來做分割。

1
2
3
4
from langchain_text_splitters import MarkdownHeaderTextSplitter

markdown_splitter = MarkdownHeaderTextSplitter(headers_to_split_on, return_each_line=False, strip_headers=True)
markdowns = markdown_splitter.split_text(combined_text)
注意
因為是透過檔案來載入,所以這邊採用的是 TextLoader,而不是 UnstructuredMarkdownLoader。如果使用 UnstructuredMarkdownLoader 的話,會將 Markdown 字元(例如:#、##、###)刪除…
技巧
不管使用哪種 Splitter,Chunk 大小都會影響 RAG 的效果,因為如果把完整語句拆分,將會嚴重影響語意,且甚至比 Embedding model 的選擇影響還嚴重!

選擇 Embedding model

因為此處使用 OpenAI 的 LLM model,所以也採用 OpenAI 的 embedding model。而 Embedding 會將上一步所分割的 chunk 文字轉換為向量。

1
2
3
from langchain_openai.chat_models import ChatOpenAI

embeddings_model = OpenAIEmbeddings()
技巧
Embedding model 的選擇也會影響到 RAG 的效果,此處採用的是 OpenAI 預設的 text-embedding-ada-002 model 做範例,不同語言也有不同 model 的選擇。

將 Embedding 結果匯入 Chroma,並建立 Tools

Embedding 後的結果我們會儲存在 VectorDB 中,這邊我們所使用的是 Chroma

  • persist_directory 需要指定儲存的路徑,如果沒有設定則是將資料儲存在 Memory 中,當程式執行完後就結束了,不會保留。
  • 使用 RetrievalQA 建立 chain,將 LLM 及 Chroma 串起來
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
persist_directory = 'db'
docsearch = Chroma.from_documents(
    markdowns,
    embeddings_model,
    collection_name="state-of-union",
    persist_directory=persist_directory
)

ssl_certificate_qa = RetrievalQA.from_chain_type(
    llm=client, chain_type="stuff", retriever=docsearch.as_retriever()
)
注意
VectorDBQA 的設定已經被棄用,需要改使用 RetrievalQA

有了前面辛苦的設定,我們就可以將它新增到我們的 Tool List 中

1
2
3
4
5
6
7
8
tools = [
    Tool(
        name="SSL Certificate QA System",
        func=ssl_certificate_qa.run,
        description="This is a RAG Tool that uses markdown for embedding. It should be prioritized for questions related to SSL certificates. This tool will generate PromQL queries related to SSL, which can be used by the Prometheus monitoring tool."
    ),
    prometheus_tool,
]
注意
再次強調,此處的 description 非常重要!!因為 Agent 會根據 description 來決定是否調用此工具。

執行結果

剩餘的程式就如同前一篇 Custom Prometheus Tool 所以介紹的,只需要修改問題即可 (再請各位換成自己系統所使用到的域名)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
# 定義 ReAct agent
custom_agent = create_react_agent(client, tools, prompt_template)

# 設置代理執行器
agent_executor = AgentExecutor.from_agent_and_tools(
    agent=custom_agent,
    tools=tools,
    verbose=True,
    max_iterations=10,  # 設定最大的重複執行次數
    handle_parsing_errors=True,  # 解析錯誤時嘗試重新執行
    return_intermediate_steps=True,
)

# 詢問範例
query = "取得 `www.langchain-agent-example.com` SSL 憑證的剩餘天數"
response = agent_executor.invoke({"input": query})

# 獲取最終結果
final_result = response.get('output', '')
print("最終結果:", final_result)

最後,當我們執行程式,可以看類似下面的結果:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
> Entering new AgentExecutor chain...
Thought: To find the remaining days for the SSL certificate of `www.langchain-agent-example.com`, I will use the SSL Certificate QA System tool to generate a PromQL query related to SSL certificates. 

Action: SSL Certificate QA System  
Action Input: `www.langchain-agent-example.com`  
The complete URL for the domain is: `https://www.langchain-agent-example.com:443`. 

The PromQL query to check the remaining days of the SSL certificate would be: 

promql floor((ssl_cert_not_after{instance="https://www.langchain-agent-example.com:443"} - time())/24/60/60)
I now have the PromQL query to check the remaining days of the SSL certificate for `www.langchain-agent-example.com`. Next, I will execute this query using the Prometheus Query tool to get the actual remaining days.

Action: Prometheus Query  
Action Input: `floor((ssl_cert_not_after{instance="https://www.langchain-agent-example.com:443"} - time())/24/60/60)`  
{'status': 'success', 'data': {'resultType': 'vector', 'result': [{'metric': {'cn': '*.langchain-agent-example.com', 'dnsnames': ',*.langchain-agent-example.com,langchain-agent-example.com,', 'instance': 'https://www.langchain-agent-example.com:443', 'issuer_cn': 'Sectigo RSA Domain Validation Secure Server CA', 'job': 'probe/monitoring/ssl-exporter', 'namespace': 'monitoring', 'serial_no': '182062631559687927624645233229527163842'}, 'value': [1722931289.104, '90']}, {'metric': {'cn': 'AAA Certificate Services', 'instance': 'https://www.langchain-agent-example.com:443', 'issuer_cn': 'AAA Certificate Services', 'job': 'probe/monitoring/ssl-exporter', 'namespace': 'monitoring', 'serial_no': '1'}, 'value': [1722931289.104, '1608']}, {'metric': {'cn': 'Sectigo RSA Domain Validation Secure Server CA', 'instance': 'https://www.langchain-agent-example.com:443', 'issuer_cn': 'USERTrust RSA Certification Authority', 'job': 'probe/monitoring/ssl-exporter', 'namespace': 'monitoring', 'serial_no': '158627644428339158458651716034459389575'}, 'value': [1722931289.104, '2338']}, {'metric': {'cn': 'USERTrust RSA Certification Authority', 'instance': 'https://www.langchain-agent-example.com:443', 'issuer_cn': 'AAA Certificate Services', 'job': 'probe/monitoring/ssl-exporter', 'namespace': 'monitoring', 'serial_no': '76359301895803385872276638154032301461'}, 'value': [1722931289.104, '1608']}]}}The query returned multiple results for different SSL certificates associated with the domain `www.langchain-agent-example.com`. The remaining days for each certificate are as follows:

1. **Certificate from Sectigo RSA Domain Validation Secure Server CA**: 90 days remaining.
2. **Certificate from AAA Certificate Services**: 1608 days remaining.
3. **Certificate from USERTrust RSA Certification Authority**: 2338 days remaining.

Since there are multiple certificates, I will focus on the one with the shortest remaining time, which is 90 days.

Final Answer: The remaining days for the SSL certificate of `www.langchain-agent-example.com` is 90 days.

> Finished chain.
最終結果: The remaining days for the SSL certificate of `www.langchain-agent-example.com` is 90 days.

LLM 由原先不懂 ssl_exporter 的 PromQL,但透過 RAG 的方式,將外部文件整合進系統,從而提升 Agent 的能力。最終,可以讓我們得到想要的結果。

Streamlit Web

Streamlit 是一個專為機器學習和資料科學設計的開源框架,不需要任何網頁開發知識,只需使用 Python 即可輕鬆構建 Dashboard 或應用程式。且內建了多種 UI 元件,如文字框、按鈕、圖表和地圖,並與 pandas、Matplotlib、Plotly 等常用的 Python 套件無縫整合,使得資料分析和視覺化工作變得非常簡單。

隨著大型語言模型(LLM)應用的興起,Streamlit 也提供了對話相關的 UI 元件,適合用來開發個人專屬的 LLM 應用,快速製作 Web 應用程式。

安裝套件

1
pip install langchain streamlit

Using an Agent with Tools

先將以下程式註解或移除

1
2
3
4
5
6
7
# 詢問範例
query = "取得 `www.langchain-agent-example.com` SSL 憑證的剩餘天數"
response = agent_executor.invoke({"input": query})

# 獲取最終結果
final_result = response.get('output', '')
print("最終結果:", final_result)

接著新增以下程式即可

1
2
3
4
5
6
7
8
9
streamlit_callback = StreamlitCallbackHandler(streamlit.container())
if prompt := streamlit.chat_input():
    streamlit.chat_message("user").write(prompt)
    with streamlit.chat_message("assistant"):
        streamlit_callback = StreamlitCallbackHandler(streamlit.container())
        response = agent_executor.invoke(
            {"input": prompt}, {"callbacks": [streamlit_callback]}
        )
        streamlit.write(response["output"])

執行時,會在本地自動開啟 Streamlit Web (localhost:8501),輸入問題,即可觀察到 LLM 的回應。

1
streamlit run main.py

/images/monitoring/streamlit.png
Streamlit Web

LangSmith

目前介紹到這邊,讀者應該可以感受到 LangChain 功能的強大,但也因為 LangChain + LLM 的關係,也非常不容易進行除錯,甚至有時會讓人有種黑箱的感覺。但如果能透過較好的 UI 工具,肯定能減少在除錯上的困難,而 LangSmith 就是專門處理這個問題的工具。

LangSmith 是一個與 LangChain 高度整合的服務,提供開發者追蹤、監控和部署語言模型應用的功能,幫助快速調整 Chain、Tool 或 Agent,可視化各元件之間的關聯和使用情況,評估不同 Prompt 和 LLM,確保在資料上的品質,生成可觀測性的分析。

取得 LangSmith API Key

首先,需要先到 LangSmith 註冊,登入後切換到 Settings 頁面申請 API Key,如下圖:

/images/monitoring/langsmith_api.png
申請 API Key

接下來,僅需要設定環境變數即可使用 (就是那麼簡單,不要懷疑🤣)

1
2
3
export LANGCHAIN_TRACING_V2=true
export LANGCHAIN_API_KEY=<your-api-key>
export LANGCHAIN_PROJECT=<your-project-name>

最後,只要執行程式就可以在 LangSmith 中,看到執行的過程與結果啦!

/images/monitoring/langsmith_result.png
LangSmith 執行結果

結論

本篇文章在前一篇基礎上,進一步探討了如何透過 RAG 技術提升 LangChain Agent 的能力,並使用 Streamlit 建立直觀的 WebUI 增強用戶體驗。此外,也介紹了 LangSmith 這個與 LangChain 高度整合的服務,幫助開發者追蹤、監控和部署語言模型應用,提供了強大的除錯和可觀測性功能。

透過這些工具和技術,我們能夠構建出更靈活、精確且強大的自然語言查詢系統,不僅提升了系統的應用範圍和能力,還讓開發過程更加有效率和直觀。希望這些內容能夠幫助大家更好地理解和應用 LangChain 及其相關工具,為你的開發工作帶來實質性的幫助和改進。