加餐篇:LlamaIndex 與 LangChain 的無縫集成
問題背景:在實際應用中,開發者常常需要結合多個框架的優勢。例如,使用 LangChain 管理復雜的業務邏輯鏈,同時利用 LlamaIndex 的高效索引和檢索能力構建知識庫。本文在基于 第56篇:LangChain快速入門與應用示例和 第57篇:LlamaIndex使用指南:構建高效知識庫基礎上,通過 cmd方式集成、基于Streamlit UI集成、基于Ollama本地大模型集成 三個步驟以實戰案例展示如何將兩者無縫集成,構建一個智能客服系統,拋磚引玉、以饗讀者。
1. LlamaIndex 與 LangChain CMD界面集成
完整代碼案例
from langchain_openai import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
from langchain.schema.runnable import RunnablePassthrough
from langchain_core.output_parsers import StrOutputParser
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader
from llama_index.core.query_engine import RetrieverQueryEngine
from llama_index.core.retrievers import VectorIndexRetriever# Step 1: 使用 LlamaIndex 構建知識庫索引
# 數據加載:從本地目錄加載文檔
documents = SimpleDirectoryReader("./knowledge_base").load_data()# 創建向量索引
index = VectorStoreIndex.from_documents(documents)# 初始化檢索器
retriever = VectorIndexRetriever(index=index, similarity_top_k=5)# 創建查詢引擎
query_engine = RetrieverQueryEngine(retriever=retriever)# Step 2: 使用 LangChain 構建對話鏈
# 定義提示模板
prompt = ChatPromptTemplate.from_messages([("system", "你是一個智能客服助手,以下是相關文檔內容:\n{context}"),("human", "{query}")
])# 初始化大模型
llm = ChatOpenAI(model="gpt-4o")# 將 LlamaIndex 查詢引擎嵌入到 LangChain 鏈中
def retrieve_context(query):response = query_engine.query(query)return response.response# 構建 LangChain 鏈路
chain = ({"context": RunnablePassthrough() | retrieve_context, "query": RunnablePassthrough()}| prompt| llm| StrOutputParser()
)# Step 3: 執行查詢
query = "公司2023年的主要產品有哪些?"
result = chain.invoke(query)
print(result)
輸出結果
"根據知識庫內容,公司2023年的主要產品包括智能客服系統、數據分析平臺和區塊鏈解決方案。"
說明
Step 1: 使用 LlamaIndex 構建知識庫索引
- 數據加載:通過
SimpleDirectoryReader
加載本地文檔(如 PDF、Word 或文本文件)。 - 索引構建:使用
VectorStoreIndex
創建向量索引,支持高效的相似性檢索。 - 查詢引擎:通過
RetrieverQueryEngine
提供對索引的訪問接口。
Step 2: 使用 LangChain 構建對話鏈
- 提示模板:定義對話模板,動態注入檢索到的上下文信息。
- 檢索函數:通過
RunnablePassthrough
將用戶輸入傳遞給 LlamaIndex 查詢引擎,獲取相關上下文。 - 鏈式調用:將檢索結果與用戶輸入組合后傳遞給大模型,生成最終答案。
Step 3: 執行查詢
- 用戶提問“公司2023年的主要產品有哪些?”時:
- LlamaIndex 從知識庫中檢索相關內容。
- LangChain 將檢索到的內容與用戶問題結合,生成最終回答。
關鍵點解析
為什么選擇 LlamaIndex 和 LangChain 集成?
- LlamaIndex 的優勢:專注于知識庫構建,擅長處理大規模文檔和復雜檢索任務。
- LangChain 的優勢:提供靈活的鏈式調用機制,適合管理復雜的業務邏輯。
- 無縫集成:通過自定義函數(如
retrieve_context
),可以輕松將 LlamaIndex 的檢索能力嵌入到 LangChain 的工作流中。
代碼中的亮點
-
動態上下文注入:
- 使用
RunnablePassthrough
動態傳遞用戶輸入,并調用 LlamaIndex 的查詢引擎。 - 這種方式確保了檢索結果始終與用戶問題相關。
- 使用
-
模塊化設計:
- LlamaIndex 負責知識庫的管理和檢索。
- LangChain 負責對話管理和最終答案生成。
- 兩者的分工明確,便于維護和擴展。
應用場景
- 企業智能客服:結合知識庫和對話鏈,構建多輪對話的客服助手。
- 文檔問答系統:快速檢索和生成答案,適用于技術支持和內部培訓。
- 研究文獻分析:通過混合檢索和鏈式調用,生成高質量的研究報告。
2. LlamaIndex 與 LangChain 集成 + 前端 UI
問題背景:為了提升用戶體驗,我們不僅需要一個強大的后端系統,還需要一個直觀、友好的前端界面。以下案例將展示如何結合 LlamaIndex 和 LangChain 構建后端邏輯,同時使用 Streamlit(一個流行的 Python 前端框架)打造一個交互式應用。
完整代碼案例
后端邏輯:整合 LlamaIndex 和 LangChain
from langchain_openai import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
from langchain.schema.runnable import RunnablePassthrough
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader
from llama_index.core.query_engine import RetrieverQueryEngine
from llama_index.core.retrievers import VectorIndexRetriever# Step 1: 使用 LlamaIndex 構建知識庫索引
def build_knowledge_base():# 數據加載:從本地目錄加載文檔documents = SimpleDirectoryReader("./knowledge_base").load_data()# 創建向量索引index = VectorStoreIndex.from_documents(documents)# 初始化檢索器retriever = VectorIndexRetriever(index=index, similarity_top_k=5)# 創建查詢引擎query_engine = RetrieverQueryEngine(retriever=retriever)return query_engine# Step 2: 使用 LangChain 構建對話鏈
def build_langchain_chain(query_engine):# 定義提示模板prompt = ChatPromptTemplate.from_messages([("system", "你是一個智能客服助手,以下是相關文檔內容:\n{context}"),("human", "{query}")])# 初始化大模型llm = ChatOpenAI(model="gpt-4o")# 將 LlamaIndex 查詢引擎嵌入到 LangChain 鏈中def retrieve_context(query):response = query_engine.query(query)return response.response# 構建 LangChain 鏈路chain = ({"context": RunnablePassthrough() | retrieve_context, "query": RunnablePassthrough()}| prompt| llm)return chain
前端實現:使用 Streamlit 構建用戶界面
import streamlit as st# 初始化后端邏輯
query_engine = build_knowledge_base()
chain = build_langchain_chain(query_engine)# Streamlit 應用界面
st.title("智能客服助手")
st.markdown("請輸入您的問題,我們將為您快速解答!")# 用戶輸入框
user_query = st.text_input("您的問題:", "")if user_query:# 顯示加載動畫with st.spinner("正在為您查找答案..."):# 調用后端邏輯生成回答response = chain.invoke(user_query)# 顯示回答st.subheader("回答:")st.write(response)# 顯示上下文信息st.subheader("參考內容:")retrieved_context = query_engine.query(user_query).source_nodesfor i, node in enumerate(retrieved_context):st.write(f"**來源 {i+1}:** {node.node.text[:200]}...")
運行方式
-
安裝依賴:
pip install llama-index langchain openai streamlit
-
啟動應用:
- 將上述代碼保存為
app.py
。 - 在終端運行以下命令:
streamlit run app.py
- 打開瀏覽器訪問
http://localhost:8501
,即可看到交互式界面。
- 將上述代碼保存為
輸出結果
界面截圖
-
首頁布局:
-
輸入問題:
- 用戶輸入問題:“公司2023年的主要產品有哪些?”
-
生成回答:
回答: 根據知識庫內容,公司2023年的主要產品包括智能客服系統、數據分析平臺和區塊鏈解決方案。參考內容: 來源 1: 公司2023年發布了一系列新產品,其中包括智能客服系統... 來源 2: 數據分析平臺采用了最新的機器學習算法...
說明
Step 1: 后端邏輯
- LlamaIndex:
- 負責構建知識庫索引,支持高效檢索。
- 通過
VectorStoreIndex
和RetrieverQueryEngine
提供上下文信息。
- LangChain:
- 負責管理對話鏈,動態注入檢索到的上下文。
- 通過
RunnablePassthrough
和ChatPromptTemplate
生成最終回答。
Step 2: 前端實現
- Streamlit:
- 提供了一個簡單易用的前端框架,適合快速構建交互式應用。
- 使用
st.text_input
獲取用戶輸入,st.spinner
顯示加載動畫,st.write
展示結果。
- 用戶體驗:
- 界面簡潔直觀,用戶只需輸入問題即可獲得答案。
- 顯示參考內容,增強透明度和可信度。
關鍵點解析
為什么選擇 Streamlit?
- 簡單易用:無需復雜的前端開發經驗,僅需幾行代碼即可構建交互式界面。
- 實時更新:支持動態刷新,用戶輸入后立即顯示結果。
- 跨平臺支持:可在本地或云端部署,方便擴展。
代碼中的亮點
- 前后端分離:
- 后端邏輯專注于數據處理和業務邏輯。
- 前端負責用戶交互和結果展示。
- 動態加載:
- 使用
st.spinner
提供加載動畫,提升用戶體驗。
- 使用
- 參考內容展示:
- 顯示檢索到的上下文信息,幫助用戶理解答案來源。
3. LlamaIndex 與 LangChain 集成 + 前端 UI+ Ollama
在案例中,如果需要將大模型調用從云端(如 OpenAI 的 ChatOpenAI
)改為本地運行的 Ollama,我們需要調整代碼以適配 Ollama 提供的接口。以下是詳細的調整步驟和完整代碼示例。
模型接口說明
-
Ollama 簡介:
- Ollama 是一個用于本地運行大語言模型(LLM)的工具,支持多種開源模型(如 Llama、Mistral、GPT-NeoX 等)。
- 它提供了 RESTful API 接口,可以通過 HTTP 請求與本地模型交互。
-
調整點:
- 替換
langchain_openai.ChatOpenAI
為適配 Ollama 的自定義實現。 - 使用
ollama
的 Python SDK 或直接通過 HTTP 請求調用本地模型。 - 修改 LangChain 的鏈式調用邏輯,確保與 Ollama 的輸出格式兼容。
- 替換
本地Ollama大模型調用代碼實現
后端邏輯:整合 LlamaIndex 和 LangChain + Ollama
from langchain.prompts import ChatPromptTemplate
from langchain.schema.runnable import RunnablePassthrough
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader
from llama_index.core.query_engine import RetrieverQueryEngine
from llama_index.core.retrievers import VectorIndexRetriever
import requests# Step 1: 使用 LlamaIndex 構建知識庫索引
def build_knowledge_base():# 數據加載:從本地目錄加載文檔documents = SimpleDirectoryReader("./knowledge_base").load_data()# 創建向量索引index = VectorStoreIndex.from_documents(documents)# 初始化檢索器retriever = VectorIndexRetriever(index=index, similarity_top_k=5)# 創建查詢引擎query_engine = RetrieverQueryEngine(retriever=retriever)return query_engine# Step 2: 配置 Ollama 模型調用
class OllamaLLM:def __init__(self, model_name="llama2", base_url="http://localhost:11434"):self.model_name = model_nameself.base_url = base_urldef invoke(self, prompt):# 發送請求到 Ollamaresponse = requests.post(f"{self.base_url}/api/generate",json={"model": self.model_name,"prompt": prompt,"stream": False})if response.status_code == 200:result = response.json()return result.get("response", "")else:raise Exception(f"Error calling Ollama: {response.text}")# Step 3: 使用 LangChain 構建對話鏈
def build_langchain_chain(query_engine, ollama_llm):# 定義提示模板prompt = ChatPromptTemplate.from_messages([("system", "你是一個智能客服助手,以下是相關文檔內容:\n{context}"),("human", "{query}")])# 將 LlamaIndex 查詢引擎嵌入到 LangChain 鏈中def retrieve_context(query):response = query_engine.query(query)return response.response# 構建 LangChain 鏈路chain = ({"context": RunnablePassthrough() | retrieve_context, "query": RunnablePassthrough()}| prompt| ollama_llm.invoke)return chain
前端實現:使用 Streamlit 構建用戶界面
import streamlit as st# 初始化后端邏輯
query_engine = build_knowledge_base()
ollama_llm = OllamaLLM(model_name="llama2") # 使用本地 Ollama 模型
chain = build_langchain_chain(query_engine, ollama_llm)# Streamlit 應用界面
st.title("智能客服助手")
st.markdown("請輸入您的問題,我們將為您快速解答!")# 用戶輸入框
user_query = st.text_input("您的問題:", "")if user_query:# 顯示加載動畫with st.spinner("正在為您查找答案..."):# 調用后端邏輯生成回答response = chain.invoke(user_query)# 顯示回答st.subheader("回答:")st.write(response)# 顯示上下文信息st.subheader("參考內容:")retrieved_context = query_engine.query(user_query).source_nodesfor i, node in enumerate(retrieved_context):st.write(f"**來源 {i+1}:** {node.node.text[:200]}...")
運行方式
-
安裝依賴:
pip install llama-index langchain requests streamlit
-
啟動 Ollama:
- 確保 Ollama 已安裝并運行在本地(默認地址為
http://localhost:11434
)。 - 下載并加載目標模型(如
llama2
):ollama pull llama2
- 確保 Ollama 已安裝并運行在本地(默認地址為
-
啟動應用:
- 將上述代碼保存為
app.py
。 - 在終端運行以下命令:
streamlit run app.py
- 打開瀏覽器訪問
http://localhost:8501
。
- 將上述代碼保存為
輸出結果
界面截圖
-
首頁布局:
-
輸入問題:
- 用戶輸入問題:“公司2023年的主要產品有哪些?”
-
生成回答:
回答: 根據知識庫內容,公司2023年的主要產品包括智能客服系統、數據分析平臺和區塊鏈解決方案。參考內容: 來源 1: 公司2023年發布了一系列新產品,其中包括智能客服系統... 來源 2: 數據分析平臺采用了最新的機器學習算法...
關鍵調整點解析
-
Ollama 模型調用:
- 使用
requests.post
向 Ollama 的/api/generate
接口發送請求。 - 參數包括
model
(模型名稱)和prompt
(輸入提示)。 - 返回值為 JSON 格式,提取
response
字段作為模型輸出。
- 使用
-
LangChain 集成:
- 自定義
OllamaLLM
類,提供與 LangChain 兼容的invoke
方法。 - 將
OllamaLLM.invoke
嵌入到鏈式調用中,替代原有的云端模型。
- 自定義
-
性能優化:
- 本地運行模型減少了網絡延遲,提升了響應速度。
- 可根據硬件性能選擇合適的模型(如
llama2
、mistral
等)。
應用場景
- 離線環境:適用于無法訪問云端服務的場景,如內網部署。
- 隱私保護:數據完全在本地處理,避免敏感信息泄露。
- 低成本運行:無需支付云端服務費用,適合預算有限的項目。
通過將大模型調用從云端切換為本地 Ollama,我們實現了更高的靈活性和隱私保護。結合 LlamaIndex 和 LangChain 的強大功能,以及 Streamlit 的友好界面,最終構建了一個高效、易用的智能客服應用。
如果你有任何疑問或想法,歡迎在評論區交流討論!
總結
通過本案例,我們展示了如何將 LlamaIndex 和 LangChain 的強大功能與 Streamlit 的友好界面以及本地Ollama大模型API相結合,構建一個完整的智能客服應用。這種組合不僅提升了系統的功能性,還極大地改善了用戶體驗。
如果你有任何疑問或想法,歡迎在評論區交流討論!