寫在前面
跟著樓蘭老師學習【LangChain教程】2025吃透LangChain框架快速上手與深度實戰,全程干貨無廢話,三天學完,讓你少走百分之99彎路!_嗶哩嗶哩_bilibili
計算相似度
一般用的余弦相似度,這里只是演示計算。
from sklearn.metrics.pairwise import cosine_similarity
import numpy as np# 定義兩個?本
text1 = "我喜歡吃蘋果"
text2 = "我最愛吃的?果是蘋果"
text3 = "今天天?不錯"# 獲取?本向量
vector1 = np.array(embedding_model.embed_query(text1)).reshape(1,-1)
vector2 = np.array(embedding_model.embed_query(text2)).reshape(1,-1)
vector3 = np.array(embedding_model.embed_query(text3)).reshape(1,-1)# 計算余弦相似度
similarity12 = cosine_similarity(vector1, vector2)[0][0]
similarity13 = cosine_similarity(vector1, vector3)[0][0]# 計算歐氏距離
euclidean_distance12 = np.linalg.norm(vector1 - vector2)
euclidean_distance13 = np.linalg.norm(vector1 - vector3)# 計算曼哈頓距離
manhattan_distance12 = np.sum(np.abs(vector1 - vector2))
manhattan_distance13 = np.sum(np.abs(vector1 - vector3))print(f"\"{text1}\" 與 \"{text2}\" 余弦相似度:{similarity12:.4f}")
print(f"\"{text1}\" 與 \"{text3}\" 余弦相似度:{similarity13:.4f}")
print(f"\"{text1}\" 與 \"{text2}\" 歐氏距離:{euclidean_distance12:.4f}")
print(f"\"{text1}\" 與 \"{text3}\" 歐氏距離:{euclidean_distance13:.4f}")
print(f"\"{text1}\" 與 \"{text2}\" 曼哈頓距離:{manhattan_distance12:.4f}")
print(f"\"{text1}\" 與 \"{text3}\" 曼哈頓距離:{manhattan_distance13:.4f}")
利用redis構建檢索庫
如何用redis見大模型之Langchain篇——基礎操作-CSDN博客。
用add_texts的方式添加數據。
檢索器的檢索方式
similarity
?類型
similarity
?即相似度檢索,這是最基礎的向量檢索方式。它會計算查詢向量和向量存儲中所有文檔向量的相似度(通常用余弦相似度),然后按照相似度從高到低排序,返回前?k
?個文檔。在你的代碼里,k
?值為 3,意味著會返回相似度最高的 3 個文檔。
similarity_score_threshold
該類型在?similarity
?檢索基礎上增加了相似度閾值。它會先計算查詢向量和文檔向量的相似度,只返回相似度高于設定閾值的文檔,并且最多返回?k
?個文檔。但好像需要實現 _similarity_search_with_relevance_scores
方法,但langchain_redis
庫中的 RedisVectorStore
尚未實現這個用于返回文檔及相關性分數的方法,因此調用失敗。
mmr
最大邊界相關檢索,目的是在保證與查詢相關性的同時,提高返回文檔的多樣性。它會先選出與查詢最相關的文檔,然后在后續選擇時,綜合考慮文檔與查詢的相關性以及和已選文檔的差異性,避免返回的文檔過于相似。
from langchain_redis import RedisConfig,RedisVectorStore
config = RedisConfig(index_name="fruit",redis_url=redis_url
)
vector_store = RedisVectorStore(embedding_model,config=config)
vector_store.add_texts(["?蕉很?","蘋果很甜","?????圓"])
vector_store.add_texts(["黃瓜很長","這個黃瓜太長了","香蕉是長條形的水果","甘蔗比香蕉還長"])# 構建檢索器,類型為similarity,檢索的?檔個數為3
retriver = vector_store.as_retriever(search_type="similarity",search_kwargs={"k":3})
retriver1 = vector_store.as_retriever(search_type="similarity",search_kwargs={"k":3})print ("\nretriver1 類型為similarity,檢索的?檔個數為3")
retriver1.invoke("??的?果是什么?")# # 構建檢索器,設置相似度閾值為 0.8
# retriever2 = vector_store.as_retriever(
# search_type="similarity_score_threshold",
# search_kwargs={"score_threshold": 0.8}
# )
# print ("\nretriever2 類型為similarity_score_threshold,檢索的?檔個數為3,相似度閾值為 0.8")
# retriever2.invoke("長長的水果是什么?")# 構建 MMR 檢索器
retriever3 = vector_store.as_retriever(search_type="mmr",search_kwargs={"k": 3, "lambda_mult": 0.5} # lambda_mult 控制相關性和多樣性的權重
)
print ("\nretriever3 類型為mmr,檢索的?檔個數為3,lambda_mult 控制相關性和多樣性的權重")
retriever3.invoke("長長的水果是什么?")
可以在resp.app中看到檢索庫信息
將檢索器鏈接到chain中
才知道自定義的函數也能放到chain中(下面代碼的format_prompt_value)
from langchain_core.prompts import ChatPromptTemplate
# 創建提示模板
prompt = ChatPromptTemplate.from_messages([("human", "{question}"),
])
# 格式轉換函數,prompt.invoke?法返回PromptValue,?retriver.invoke需要傳?的參數為str。中間做個格式轉換
def format_prompt_value(prompt_value):return prompt_value.to_string()
# 鏈式連接檢索器和提示模板
chain = prompt | format_prompt_value | retriver
# 調?鏈并傳??戶的問題
documents = chain.invoke({"question":"???甜的?果是什么?"})
for document in documents:print(document.page_content)
?meituan RAG
數據來源?
美團外賣 - 常見問題
也可以直接復制我的
?
Q:在線支付取消訂單后錢怎么返還?
訂單取消后,款項會在一個工作日內,直接返還到您的美團賬戶余額。Q:怎么查看退款是否成功?
退款會在一個工作日之內到美團賬戶余額,可在“賬號管理——我的賬號”中查看是否到賬。Q:美團賬戶里的余額怎么提現?
余額可到美團網(meituan.com)——“我的美團→美團余額”里提取到您的銀行卡或者支付寶賬號,另外,余額也可直接用于支付外賣訂單(限支持在線支付的商家)Q:余額提現到賬時間是多久?
1-7個工作日內可退回您的支付賬戶。由于銀行處理可能有延遲,具體以賬戶的到賬時間為準。Q:申請退款后,商家拒絕了怎么辦?
申請退款后,如果商家拒絕,此時回到訂單頁面點擊“退款申訴”,美團客服介入處理。Q:怎么取消退款呢?
請在訂單頁點擊“不退款了”,商家還會正常送餐的。Q:前面下了一個在線支付的單子,由于未付款,訂單自動取消了,這單會計算我的參與活動次數嗎?
不會。如果是未支付的在線支付訂單,可以先將訂單取消(如果不取消需要15分鐘后系統自動取消),訂單無效后,此時您再下單仍會享受活動的優惠。Q:為什么我用微信訂餐,卻無法使用在線支付?
目前只有網頁版和美團外賣手機App(非美團手機客戶端)訂餐,才能使用在線支付,請更換到網頁版和美團外賣手機App下單。Q:如何進行付款?
美團外賣現在支持貨到付款與在線支付,其中微信版與手機觸屏版暫不支持在線支付。Q:如何查看可以在線支付的商家?
你可以在商家列表頁尋找帶有“付”標識的商家,提交訂單時可以選擇支付方式。Q:美團外賣支持哪些支付方式?
現已支持美團余額、支付寶、網銀(儲蓄卡、信用卡)。Q:在線支付訂單如何退款?
商家接單前,您可以直接取消訂單,訂單金額會自動退款到美團余額;商家接單后,您在點擊“申請退款”,在線申請。提交退款申請之后,商家有24小時處理您的退款申請。商家同意退款,或24小時內沒有處理您的退款申請,您的支付金額會退款至您的美團余額。Q:在線支付的過程中,訂單顯示未支付成功,款項卻被扣了,怎么辦?
出現此問題,可能是銀行/支付寶的數據沒有即時傳輸至美團,請您不要擔心,稍后刷新頁面查看。 如半小時后仍顯示"未付款",請先聯系銀行/支付寶客服,獲取您扣款的交易號,然后致電美團外賣客服4008507777,我們會協助您解決。Q:哪些商家有優惠?都有些什么優惠?
有優惠的商家在商家列表頁均含有優惠標識;具體的優惠可以查看活動詳情或者商家詳情頁中的描述。Q:在新用戶享受的優惠中,新用戶的條件是什么?
新用戶是指第一次在美團外賣下單的用戶(同一設備、同一手機號、同一賬戶僅可享受一次)。Q:我達到了滿贈、滿減的優惠的金額,為什么沒有享受相關的優惠?
滿贈與滿減優惠是以訂單內菜品的總額來計算的,不包含配送費與包裝費。Q:超時賠付是什么意思?
超時賠付模式即:商家承諾一個送達時間和一個折扣,從用戶下單時間開始計算,如果外賣超過了承諾時間才送到,該份外賣按照折扣價收取費用。由于惡劣天氣、某些美食烹調時間過長、或者其他因素,商家會選擇性的延長承諾時間或者不做承諾。預訂單不參與超時賠付。Q:為什么提示我“賬戶存在異常,無法下單”?
包含(但不僅限于)以下行為者,系統將自動予以封禁(客服無權解封):i)有過虛假交易(編造不存在真實買賣的訂單);ii)有過惡意下單行為;Q:如何取消訂單?
如果商家尚未接單,您可以在訂單詳情頁通過“取消訂單”功能進行取消;如果商家已接單,則需要您電話聯系后由商家取消訂單。Q:我的訂單為什么被取消了?
如果商家5分鐘未接您的訂單,為了保障您的權益,系統將會為您自動取消訂單;商家接單后可能由于無法聯系到您、菜品售完等原因無法配送,因而取消了您的訂單,具體原因可查看系統發送的短信或通知。Q:如何進行催單?
您可以在訂單狀態頁面點擊“電話催單”按鈕向商家商家催單。Q:剛下單發現信息填錯了怎么辦?
如果商家尚未接單,您可以自主取消訂單;如果商家已經接單,您可以電話聯系商家后由對方取消訂單。然后重新下一單。Q:我的訂單是否被商家確認?
App用戶可以在商家確認您的訂單時收到推送通知,并且訂單狀態會實時更新;手機觸屏版及微信用戶可以刷新訂單狀態頁查看。Q:預計送達的時間為什么與我實際收餐的時間不符?
預計送達時間是系統根據用戶評價的時間進行綜合計算而得到的參考時間,餐廳的實際配送時間會受到當天的天氣、訂單量等外界因素影響。Q:為什么會出現無法下單的情況?
無法下單有很多情況,可能是菜品售完、餐廳不在營業時間等,請查看無法下單時給的提示。Q:為什么提示下單次數過多,已無法下單?
同一手機號在同一設備上一天最多可以成功提交7次訂單(在線支付以完成支付為準,貨到付款以提交訂單為準)。Q:如果對商家服務不滿意如何進行投訴?
您可以在該訂單完成評價后點擊訂單詳情頁中的意見反饋向客服投訴,或者撥打美團外賣的客服電話(400-850-7777)向客服進行投訴。Q:如何聯系客服解決問題?
您可以撥打美團外賣的客服電話(400-850-7777)或者在“我的”——>“意見反饋”頁面提交反饋。Q:我用的是手機客戶端,為什么無法定位?
請先檢查手機的網絡以及是否開啟定位功能。若確認正常,請試著在戶外或wifi環境下進行定位。Q:如何修改自己的賬戶信息?
美團外賣使用的是美團賬號,您可以在“我的”頁面修改個人賬號信息,也可以在美團網賬號頁面修改個人賬號。Q:為什么有時需要輸入短信驗證碼?
為了保障您的賬號安全及商家利益,對于新用戶及一些有異常行為的下單系統會提示您輸入短信驗證碼。如果遲遲未接收到短信驗證碼,您同樣可以選擇接聽語音驗證碼。
文檔切分
langchain有專門的切分工具CharacterTextSplitter,之所以切分不到31個塊,是因為會首先保證在chunk_size字符內最大字符,然后根據separator字符進行切分,chunk_overlap是作為保留上下文信息交叉部分保留字符數量(也有其他辦法,比如對用LLM對前文進行一次總結)
from langchain_text_splitters import CharacterTextSplitter
# 切分?檔 塊的內容限制在500字符以內 塊與塊之間有重疊 重疊的字符數為0 分隔符為兩個換行符 保留換行符
text_splitter = CharacterTextSplitter(chunk_size=500, chunk_overlap=0,separator="\n\n",keep_separator=True)
segments = text_splitter.split_documents(documents)
print(len(segments))
for segment in segments:print(segment.page_content)print("--------")
chain邏輯
chain都是從左到右運行,一共有以下部分組成
- 輸入映射部分:一個字典,負責處理和映射輸入數據。
- 提示詞模板部分:
prompt_template
,把處理后的輸入數據填充到提示詞模板里。 - 大語言模型部分:
llm
,依據提示詞模板生成的提示信息生成回答。 - 輸出解析部分:
StrOutputParser()
,將大語言模型的輸出解析成字符串。
第一個字典里,"context":itemgetter("question") | retriever | collect_documents是為了將用戶問題與向量數據庫進行匹配,匹配到合適的文本塊,作為“context”的內容
chain = ({"context":itemgetter("question") | retriever | collect_documents, # 這行是用retriever召回用戶問題相關的document"question":itemgetter("question")}|prompt_template|llm|StrOutputParser()
)
遇到的坑
使用docker和resp.app一起存儲信息時,第一次按照大模型之Langchain篇——基礎操作-CSDN博客沒有出現什么問題,重啟電腦之后發現報錯,顯示ResponseError: unknown command 'MODULE'Cell Execution Error
原因是因為resp.app版本太低,而docker鏡像的版本沒問題,此時電腦中有兩個redis程序,用RedisVectorStore時識別到了低版本的resp.app,而沒有用docker鏡像的版本。按照以下操作解決
詳細步驟如下:
-
找到并停止所有非 Docker 的 Redis 實例:
-
Windows 操作系統上:
-
打開任務管理器 (
Ctrl + Shift + Esc
)。 -
切換到“服務”選項卡。
-
查找名稱中包含 "redis" 的服務。如果有,右鍵點擊并選擇“停止”。
-
切換到“詳細信息”選項卡。
-
查找
redis-server.exe
進程。如果存在,選中它并點擊“結束任務”。 -
如果您是在 WSL2 中運行的 Linux 子系統,也需要檢查 WSL2 中是否有其他 Redis 進程。
-
-
-
停止并刪除任何可能存在問題的 Docker 容器: 打開您的命令行(
Bashcmd.exe
或 PowerShell):docker stop redis-stack docker rm redis-stack
(如果您之前沒有設置持久化,這會丟失上次的數據。后續我們會解決這個問題。)
-
(可選但推薦)刪除舊的 Redis Stack Docker 鏡像: 這可以確保您拉取到最新且健康的鏡像。
Bashdocker rmi redis/redis-stack:latest
-
重新啟動帶有持久化卷的 Redis Stack Docker 容器: 使用以下命令,它不僅啟動容器,還設置了數據持久化,這樣以后重啟就不會丟失數據了。
Bashdocker run -d --name redis-stack -p 6379:6379 -p 8001:8001 \-v redis-stack-data:/data \ # <-- 這一行非常重要,用于持久化數據redis/redis-stack:latest
-
驗證 Docker 容器中的 Redis 版本和模塊: 等待幾秒鐘讓容器完全啟動。然后,執行以下命令進入容器內部的 Redis CLI 并檢查模塊列表:
Bashdocker exec -it redis-stack redis-cli MODULE LIST
這次,您必須看到輸出中包含
search
模塊。 并且您也可以輸入INFO server
來確認 Redis 版本是 7.x (或更新的版本),而不是 3.x。 -
在 RESP.app 中連接: 現在,打開 RESP.app,確保連接配置是
localhost:6379
。連接成功后,RESP.app 應該會顯示 Redis 版本是 7.x (或更高),并且您應該能在其界面中看到 RediSearch 相關的索引管理選項(盡管不直接顯示為search
模塊名稱,但其功能會體現在 RESP.app 對 Redis Stack 的支持上)。 -
再次運行您的 Python 代碼: 如果前面的所有步驟都成功,并且
MODULE LIST
確認了search
模塊的存在,那么您的 Python 代碼應該能正常運行,不再報錯unknown command 'MODULE'
。