RAG實踐:Routing機制與Query Construction策略

Routing機制與Query Construction策略

  • 前言
  • Routing
    • Logical Routing
      • ChatOpenAI
      • Structured
      • Routing Datasource
      • Conclusion
    • Semantic Routing
      • Embedding & LLM
      • Prompt
      • Rounting Prompt
      • Conclusion
  • Query Construction
    • Grab Youtube video information
    • Structured
    • Prompt
  • Github
  • References

前言

本文引用上一篇博客的作法。在本地開啟一個代理服務器,然后使用OpenAI的ChatOpenAI作為聊天接口客戶端,使其發送的請求鏈接到我們的本地服務器。

Routing

在傳統的 RAG 架構中,所有查詢都走統一的 Retriever和 Prompt 模板,這在多源數據或多任務系統中存在檢索結果不相關、內容不精準、用戶意圖模糊等局限性。為了解決這一問題,Routing機制可以根據用戶提出的問題,智能地路由到最相關的知識源或處理流程中,以提升回答的精準性與效率。

Logical Routing

ChatOpenAI

如前言所述,使用ChatOpenAI聊天接口客戶端,但不適用GPT模型。

os.environ['VLLM_USE_MODELSCOPE'] = 'True'
chat = ChatOpenAI(model='Qwen/Qwen3-0.6B',openai_api_key="EMPTY",openai_api_base='http://localhost:8000/v1',stop=['<|im_end|>'],temperature=0
)

在這里插入圖片描述
Fig .1 Logical Routing framework diagram

Structured

Prompt中,指示LLM根據當前編程語言選擇最相關的數據源。然后通過|管道運算符傳入with_structured_output。其中, with_structured_output的作用是讓大模型生成和RouteQuery數據格式一樣的數據結構。也稱結構化數據。

class RouteQuery(BaseModel):"""Route a user query to the most relevant datasource."""datasource: Literal["python_docs", "js_docs", "golang_docs"] = Field(...,description="Given a user question choose which datasource would be most relevant for answering their question",)# 生成結構化對象;其目的是讓llm嚴格地按照RouteQuery結構體格式化為對應的JSON格式,并自動解析成Python對象。”
"""
數據結構:
RouteQuery(datasource='python_docs'  # 或 'js_docs' 或 'golang_docs'
)
JSON格式:
{"datasource": "python_docs"
}
"""
structured_llm = chat.with_structured_output(RouteQuery)# Prompt
system = """You are an expert at routing a user question to the appropriate data source.Based on the programming language the question is referring to, route it to the relevant data source."""prompt = ChatPromptTemplate.from_messages([("system", system),("human", "{question}"),]
)# Define router
router = prompt | structured_llm

當運行這一部分之后,LLM只會生成["python_docs", "js_docs", "golang_docs"]三者中的其中一個,因為datasource: Literal["python_docs", "js_docs", "golang_docs"] 指定了它們三個作為候選值。輸出的結果如下所示。

"""
數據結構:
RouteQuery(datasource='python_docs'  # 或 'js_docs' 或 'golang_docs'
)
JSON格式:
{"datasource": "python_docs"
}
"""

在這里插入圖片描述
Fig .2 Data structured flow chart

Routing Datasource

Question中給出需要判斷的編程語言。然后經過上一節Structured的運算后,得到一個結構化數據。最終只需要調用choose_route匹配對應數據源即可。

question = """Why doesn't the following code work:from langchain_core.prompts import ChatPromptTemplateprompt = ChatPromptTemplate.from_messages(["human", "speak in {language}"])
prompt.invoke("french")
"""# result = router.invoke({"question": question})
def choose_route(result):if "python_docs" in result.datasource.lower():### Logic herereturn "chain for python_docs"elif "js_docs" in result.datasource.lower():### Logic herereturn "chain for js_docs"else:### Logic herereturn "golang_docs"full_chain = router | RunnableLambda(choose_route)full_chain.invoke({"question": question})

Conclusion

上述內容通過一個甄別編程語言的案例,講述了如何結構化數據,以及如何根據結構化后的數據選擇對應的數據源。這有利于我們在實際應用中,根據用戶所提問題,Rounting到最相關的數據源或向量數據庫中,可以極大地提升召回率。

Semantic Routing

Embedding & LLM

定義ModelScope社區中開源的EmbeddingText Generation模型。

embedding = ModelScopeEmbeddings(model_id='iic/nlp_corom_sentence-embedding_english-base')
# 使用vllm部署OpenAI Serve,然后使用ChatOpenAI
os.environ['VLLM_USE_MODELSCOPE'] = 'True'
chat = ChatOpenAI(model='Qwen/Qwen3-0.6B',openai_api_key="EMPTY",openai_api_base='http://localhost:8000/v1',stop=['<|im_end|>'],temperature=0
)

Prompt

定義兩個prompt template,并對其向量化。用于后續根據用戶所提問題,選擇合適的prompt

physics_template = """You are a very smart physics professor. \
You are great at answering questions about physics in a concise and easy to understand manner. \
When you don't know the answer to a question you admit that you don't know.Here is a question:
{query}"""math_template = """You are a very good mathematician. You are great at answering math questions. \
You are so good because you are able to break down hard problems into their component parts, \
answer the component parts, and then put them together to answer the broader question.Here is a question:
{query}"""prompt_templates = [physics_template, math_template]
prompt_embeddings = embedding.embed_documents(prompt_templates)

在這里插入圖片描述
Fig .3 Semantic Routing framework diagram

Rounting Prompt

對用戶查詢進行向量化,便于計算用戶查詢和prompt template之間的余弦相似度,根據相似度最高的下標,獲取對應的prompt。最終交予LLM處理。

# 根據計算余弦相似度,得到輸入`query`和`templates`中相似度最高的一個`template`
def prompt_router(input):# 向量化 `query`query_embedding = embedding.embed_query(input["query"])# 計算輸入`query`和`prompt`之間的余弦相似度similarity = cosine_similarity([query_embedding], prompt_embeddings)[0]# 以相似度最高的下標獲取對應的templatemost_similar = prompt_templates[similarity.argmax()]# Chosen promptprint("Using MATH" if most_similar == math_template else "Using PHYSICS")return PromptTemplate.from_template(most_similar)# RunnablePassthrough直接返回原值
chain = ({"query": RunnablePassthrough()}| RunnableLambda(prompt_router)| chat| StrOutputParser()
)answer = chain.invoke("What's a black hole")
print(answer)

Conclusion

上述內容描述了一種根據用戶查詢動態匹配Prompt的策略。

Query Construction

Grab Youtube video information

國內訪問下述內容,可能會出現urllib.error.HTTPError: HTTP Error 400: Bad Request異常。為了解決這一問題,我們通過另外一種方式,同樣可以構造datasource

docs = YoutubeLoader.from_youtube_url("https://www.youtube.com/watch?v=pbAd8O1Lvm4", add_video_info=False
).load()print(docs[0].metadata)

通過subprocess.run執行一個腳本,并使用yt-dlp下載視頻信息,然后以JSON數據格式輸出。最后,根據數據信息構造我們所需的datasource即可。

result = subprocess.run(["yt-dlp", "--dump-json", f"https://www.youtube.com/watch?v=pbAd8O1Lvm4"],capture_output=True, text=True)
video_info = json.loads(result.stdout)metadata = {"source": 'pbAd8O1Lvm4',"title": video_info.get("title", "Unknown"),"description": video_info.get("description", "Unknown"),"view_count": video_info.get("view_count", 0),"thumbnail_url": video_info.get("thumbnail", ""),"publish_date": datetime.strptime(video_info.get("upload_date", "19700101"), "%Y%m%d").strftime("%Y-%m-%d 00:00:00"),"length": video_info.get("duration", 0),"author": video_info.get("uploader", "Unknown"),
}

Structured

下列定義了一個結構化搜索查詢模式,與Routing中的Structured一樣。其目的是將自然語言轉為結構化搜索查詢。

class TutorialSearch(BaseModel):"""Search over a database of tutorial videos about a software library."""content_search: str = Field(...,description="Similarity search query applied to video transcripts.",)title_search: str = Field(...,description=("Alternate version of the content search query to apply to video titles. ""Should be succinct and only include key words that could be in a video ""title."),)min_view_count: Optional[int] = Field(None,description="Minimum view count filter, inclusive. Only use if explicitly specified.",)max_view_count: Optional[int] = Field(None,description="Maximum view count filter, exclusive. Only use if explicitly specified.",)earliest_publish_date: Optional[date] = Field(None,description="Earliest publish date filter, inclusive. Only use if explicitly specified.",)latest_publish_date: Optional[date] = Field(None,description="Latest publish date filter, exclusive. Only use if explicitly specified.",)min_length_sec: Optional[int] = Field(None,description="Minimum video length in seconds, inclusive. Only use if explicitly specified.",)max_length_sec: Optional[int] = Field(None,description="Maximum video length in seconds, exclusive. Only use if explicitly specified.",)def pretty_print(self) -> None:for field in self.__fields__:if getattr(self, field) is not None and getattr(self, field) != getattr(self.__fields__[field], "default", None):print(f"{field}: {getattr(self, field)}")

在這里插入圖片描述
Fig .4 Data structured flow chart

Prompt

下述Prompt引導模型將用戶的自然語言問題轉化為結構化的數據庫查詢指令。

system = """You are an expert at converting user questions into database queries. \
You have access to a database of tutorial videos about a software library for building LLM-powered applications. \
Given a question, return a database query optimized to retrieve the most relevant results.If there are acronyms or words you are not familiar with, do not try to rephrase them."""
prompt = ChatPromptTemplate.from_messages([("system", system),("human", "{question}"),]
)# 根據問題語義,將問題中涉及的內容映射到 metadata 的結構化字段中。
structured_llm = llm.with_structured_output(TutorialSearch)
query_analyzer = prompt | structured_llm

對于用戶的提問,則將此Question根據Prompt進行結構化。其目的是將用戶提問中所包含的單詞映射到datasource中合適的字段。

query_analyzer.invoke({"question": "rag from scratch"}).pretty_print()

上述代碼運行之后,LLM會根據語義自動構造合適的結構化數據。

content_search: rag from scratch
title_search: rag from scratch

再例如,Question2023 年在 Chat Langchain 上發布的視頻,其中很明顯日期應該對應datasource字段中的包含時間日期的對應項,例如earliest_publish_date,latest_publish_date

query_analyzer.invoke({"question": "videos on chat langchain published in 2023"}
).pretty_print()
content_search: chat langchain
title_search: 2023
earliest_publish_date: 2023-01-01
latest_publish_date: 2024-01-01

Github

https://github.com/FranzLiszt-1847/LLM

References

[1] https://github.com/langchain-ai/rag-from-scratch/blob/main/rag_from_scratch_5_to_9.ipynb

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/87436.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/87436.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/87436.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

基于python的web系統界面登錄

#讓我們的電腦可以支持服務訪問 #需要一個web框架 #pip install Flask from flask import Flask, render_template,request from random import randint app Flask(__name__) app.route(/index) def index():uname request.args.get("uname")return f"主頁&am…

MATLAB Simulink 終極入門指南:從零設計智能控制系統

為什么工程師都愛Simulink? 想象一下:不寫一行代碼就能設計機器人控制器、飛行算法甚至核反應堆! MATLAB Simulink正是這樣的可視化神器。全球70%的汽車ECU、航天器控制系統用它開發。本文將帶你從零設計一個智能溫控系統,融入創新性的模糊PID控制,并生成可部署的C代碼!…

vue3 javascript 復雜數值計算操作技巧

在Vue 3中處理復雜數值計算&#xff0c;你可以采用多種策略來確保代碼的可讀性、可維護性和性能。以下是一些實用的技巧和最佳實踐&#xff1a; 1. 使用計算屬性&#xff08;Computed Properties&#xff09; Vue 3的computed屬性非常適合處理復雜的數值計算。它們是基于響應…

26.【.NET8 實戰--孢子記賬--從單體到微服務--轉向微服務】--單體轉微服務--角色權限管理

在現代企業級應用中&#xff0c;角色權限管理是保障系統安全和提升用戶體驗的核心基礎功能。一個高效的角色權限系統不僅能夠有效防止越權訪問&#xff0c;還能簡化系統的維護和擴展。本文將系統性介紹角色權限管理的核心實現思路&#xff0c;包括架構設計、性能優化、安全機制…

[VSCode] VSCode 設置 python 的編譯器

VSCode 設置 python 的編譯器 快捷鍵&#xff1a;CTRL SHIFT P 彈出 VSCode 的命令框輸入 Python : select Interpretor選擇自己需要的 python 環境&#xff1b;如 python 3.8 或者 python 3.10 版本

基于PEMFC質子交換膜燃料電池系統的simulink建模與仿真

目錄 1.課題概述 2.系統仿真結果 3.核心程序 4.系統仿真參數 5.系統原理簡介 6.參考文獻 7.完整工程文件 1.課題概述 本課題是一個燃料電池&#xff08;大概率是質子交換膜燃料電池&#xff0c;PEMFC &#xff09;的數學模型仿真框圖&#xff0c;用于模擬燃料電池的電特…

git-build-package 工具代碼詳細解讀

git-build-package&#xff08;gbp&#xff09;是一個用于從 Git 倉庫管理 Debian 軟件包的工具&#xff0c;其代碼架構和實現原理體現了對 Git 版本控制系統和 Debian 打包流程的深度整合。以下是對其代碼的詳細解讀&#xff1a; 代碼架構設計 gbp 的代碼架構設計圍繞其核心…

如何使用ChatGPT快速完成一篇論文初稿?

2小時寫完論文初稿&#xff0c;學境思源&#xff0c;聽起來是不是有點不真實&#xff1f;一鍵生成論文初稿&#xff01;但如果你有一個清晰的框架、良好的寫作節奏&#xff0c;acaids.com。再配合像ChatGPT這樣的寫作助手——真的可以做到。 這篇文章就是手把手告訴你&#xf…

Docker PowerJob

1. Docker PowerJob 1. 拉取PowerJob服務端鏡像 docker pull tjqq/powerjob-server:4.3.92. 創建數據卷目錄用于持久化數據 mkdir -p /home/docker/powerjob/logs mkdir -p /home/docker/powerjob/data mkdir -p /home/docker/powerjob/server mkdir -p /home/docker/powerjob…

Python數據可視化:NumPy生成與Matplotlib折線圖繪制

一、數據生成與可視化概述 在數據分析和科學計算領域,Python已成為最受歡迎的編程語言之一。這主要得益于其豐富的數據處理庫和強大的可視化工具。數據可視化是將抽象數據轉化為直觀圖形表示的過程,它能夠幫助我們發現數據中的模式、趨勢和異常值,從而做出更明智的決策。 …

26.多表查詢

1.笛卡爾集 創建倆表&#xff1a; -- 創建部門表&#xff08;dept&#xff09; use mysql_learn CREATE TABLE dept (deptno INT PRIMARY KEY, dname VARCHAR(50) NOT NULL, loc VARCHAR(50) );-- 創建員工表&#xff08;emp&#xff09; CREATE TABLE emp (em…

深度學習題目(僅供參考)

一、注意力和transformer 一、選擇題 注意力機制的核心步驟不包括&#xff1f; A. 計算注意力分布 B. 加權平均輸入信息 C. 隨機丟棄部分輸入 D. 打分函數計算相關性 答案&#xff1a;C&#xff08;硬性注意力雖隨機選擇輸入&#xff0c;但核心步驟仍為分布計算與加權&#xf…

WebWorker:提升前端性能的多線程利器

簡介 在現代Web開發中&#xff0c;隨著應用越來越復雜&#xff0c;JavaScript的單線程模型開始顯現其局限性。Web Workers的出現為解決這一問題提供了優雅的方案&#xff0c;它允許開發者在后臺線程中運行腳本&#xff0c;而不會影響主線程的性能。 Web Workers是HTML5標準的…

milvus教程:collection和scheme

環境配置&#xff1a;可以看上一節 一.數據庫使用 連接 Milvus Standalone創建數據庫 my_database_1&#xff08;無額外屬性&#xff09;創建數據庫 my_database_2&#xff08;設置副本數為 3&#xff09;列出所有數據庫查看默認數據庫&#xff08;default&#xff09;詳情修…

14:00開始面試,14:06就出來了,問的問題有點變態。。。

從小廠出來&#xff0c;沒想到在另一家公司又寄了。 到這家公司開始上班&#xff0c;加班是每天必不可少的&#xff0c;看在錢給的比較多的份上&#xff0c;就不太計較了。沒想到6月一紙通知&#xff0c;所有人不準加班&#xff0c;加班費不僅沒有了&#xff0c;薪資還要降40%…

Electron(01)

Electron Electron是什么 electron可以使用前端技術開發桌面應用&#xff0c;跨平臺性&#xff0c;開發一套應用&#xff0c;可以打包到三個平臺。 electron結合Chromium&#xff08;谷歌內核&#xff09;和 Node.js 和Native Api 當使用 Electron 時&#xff0c;很重要的一…

Kafka 攔截器深度剖析:原理、配置與實踐

引言 在構建高可用、可擴展的消息系統時&#xff0c;Kafka以其卓越的性能和穩定性成為眾多企業的首選。而Kafka攔截器作為Kafka生態中強大且靈活的功能組件&#xff0c;能夠在消息的生產和消費過程中實現自定義邏輯的注入&#xff0c;為消息處理流程帶來極大的擴展性和可控性。…

Flutter 與原生技術(Objective-C/Swift,java)的關系

在 iOS 開發中&#xff0c;Flutter 與原生技術&#xff08;Objective-C/Swift&#xff09;的關系 一、技術定位與核心差異 Flutter 語言&#xff1a;使用Dart 語言開發&#xff0c;通過 AOT&#xff08;提前編譯&#xff09;將代碼轉換為原生 ARM 指令&#xff0c;無需依賴 iOS…

最新期刊影響因子,基本包含全部期刊

原文鏈接&#xff1a;2024年期刊最新影響因子&#xff08;IF&#xff09; 2024年期刊最新影響因子&#xff08;IF&#xff09; BioinfoR生信筆記 &#xff0c;注于分享生物信息學相關知識和R語言繪圖教程。

java 設計模式_行為型_14策略模式

14.策略模式 策略模式作為一種軟件設計模式&#xff0c;指對象有某個行為&#xff0c;但是在不同的場景中&#xff0c;該行為有不同的實現算法。 策略模式把這些算法&#xff0c;都抽取出來&#xff0c;組成一個一個的類&#xff0c;可以任意的替換&#xff0c;大大降低了代碼…