[the documentation of vllm](https://docs.vllm.ai/en/stable/). Now, you can have fun with Qwen2.5 models.

這是一個能很好體現從其他上下文中獲益的信息塊示例。單獨來看,這個信息塊的信息含量相對有限。接下來,我們來看看增加了上下文信息后的信息塊:

帶上下文的示例數據塊:

For more information, please refer to 
[the documentation of vllm](https://docs.vllm.ai/en/stable/). Now, you can have fun with Qwen2.5 models. The chunk is situated at the end of the document, following the section on deploying Qwen2.5 models with vLLM, and serves as a concluding remark encouraging users to explore the capabilities of Qwen2.5 models.

你可以想象,當模型接收到這個塊時,它對上下文有了更好的理解,并且可以提供更準確的答案。讓我們構建管道來創建這些塊。

什么是上下文檢索?

上下文檢索(由 Anthropic 引入)解決了傳統檢索增強生成 (RAG) 系統中的一個常見問題:單個文本塊通常缺乏足夠的上下文來準確檢索和理解。

上下文檢索通過在嵌入或索引之前添加特定的解釋性上下文來增強每個塊。這保留了塊與其更廣泛的文檔之間的關系,從而顯著提高了系統檢索和使用最相關信息的能力。

根據 Anthropic 的實驗:

這些改進凸顯了上下文檢索的潛力,可以提高 AI 驅動的問答系統的性能,使其更加準確和上下文感知。

上下文檢索的工作原理
上下文檢索的工作原理

我們將構建什么

我們將使用兩個示例文檔來演示上下文檢索如何改進問答系統。我們的系統將執行以下操作:

  1. 將文檔拆分成更小的信息塊。
  2. 向每個信息塊添加上下文信息,將其嵌入,并將它們存儲在數據庫中。
  3. 執行相似性搜索以找到最相關的上下文。
  4. 使用大型語言模型(LLM)根據檢索到的上下文生成用戶問題的答案。

設置環境

首先,讓我們安裝必要的庫:

pip install -Uqqq pip --progress-bar off
pip install -qqq fastembed==0.3.6 --progress-bar off
pip install -qqq sqlite-vec==0.1.2 --progress-bar off
pip install -qqq groq==0.11.0 --progress-bar off
pip install -qqq langchain-text-splitters==0.3.0 --progress-bar off

現在,讓我們導入所需的模塊:

import sqlite3
from textwrap import dedent
from typing import List

import sqlite_vec
from fastembed import TextEmbedding
from google.colab import userdata
from groq import Groq
from groq.types.chat import ChatCompletionMessage
from langchain_text_splitters import RecursiveCharacterTextSplitter
from sqlite_vec import serialize_float32
from tqdm import tqdm

語言模型設置

我們將通過 Groq API 使用 Llama 3.1。首先,讓我們設置客戶端:

client = Groq(api_key=userdata.get("GROQ_API_KEY"))
MODEL = "llama-3.1-70b-versatile"
TEMPERATURE = 0

接下來,我們將創建一個輔助函數來與模型交互。此函數將接受提示和可選的消息歷史記錄:

def call_model(prompt: str, messages=[]) -> ChatCompletionMessage:
messages.append({
"role": "user",
"content": prompt,
})
response = client.chat.completions.create(
model=MODEL,
messages=messages,
temperature=TEMPERATURE,
)
return response.choices[0].message.content

此函數向模型發送提示并返回模型的響應。您還可以傳遞消息歷史記錄以維護對話的上下文。

數據庫設置

我們將使用帶有sqlite-vec擴展的SQLite來存儲我們的文檔及其嵌入。以下是設置數據庫的方法:

db = sqlite3.connect("readmes.sqlite3")
db.enable_load_extension(True)
sqlite_vec.load(db)
db.enable_load_extension(False)

連接到數據庫后,讓我們創建必要的表:

db.execute("""
CREATE TABLE documents(
id INTEGER PRIMARY KEY AUTOINCREMENT,
text TEXT
);
""")

db.execute("""
CREATE TABLE chunks(
id INTEGER PRIMARY KEY AUTOINCREMENT,
document_id INTEGER,
text TEXT,
FOREIGN KEY(document_id) REFERENCES documents(id)
);
""")

db.execute(f"""
CREATE VIRTUAL TABLE chunk_embeddings USING vec0(
id INTEGER PRIMARY KEY,
embedding FLOAT[{document_embeddings[0].shape[0]}]
);
""")

以下是表格的分類:

這種數據庫設置允許我們有效地存儲、檢索和嵌入塊,從而便于以后執行相似性搜索。

創建數據塊

為了將文檔分解為可管理的塊以便更好地進行上下文檢索,我們將按照以下步驟操作:

  1. 將文檔文本拆分為較小的塊。
  2. 向每個數據塊添加上下文信息。
  3. 嵌入每個塊并將其與文本一起存儲在數據庫中。

我們將使用的文檔是Qwen 2.5模型和LangGraph項目的README文件。

首先,讓我們將文檔保存在數據庫中:

documents = [qwen_doc, langgraph_doc]

with db:
for doc in documents:
db.execute("INSERT INTO documents(text) VALUES(?)", [doc])

為了將文檔拆分成更小的信息塊,我們將使用LangChain中的RecursiveCharacterTextSplitter3工具:

text_splitter = RecursiveCharacterTextSplitter(chunk_size=2048, chunk_overlap=128)

我們現在可以創建塊并將它們存儲在數據庫中:

with db:
document_rows = db.execute("SELECT id, text FROM documents").fetchall()
for row in document_rows:
doc_id, doc_text = row
chunks = text_splitter.split_text(doc_text)
contextual_chunks = create_contextual_chunks(chunks, doc_text)
save_chunks(contextual_chunks)

為了給每個數據塊提供額外的上下文,我們將使用以下提示生成簡短的摘要:

CONTEXTUAL_EMBEDDING_PROMPT = """
Here is the chunk we want to situate within the whole document:
<chunk>
{chunk}
</chunk>

Here is the content of the whole document:
<document>
{document}
</document>

Please provide a short, succinct context to situate this chunk within the overall document to improve search retrieval. Respond only with the context.
"""

以下是該函數的工作原理:

def create_contextual_chunks(chunks: List[str], document: str) -> List[str]:
contextual_chunks = []
for chunk in chunks:
prompt = CONTEXTUAL_EMBEDDING_PROMPT.format(chunk=chunk, document=document)
chunk_context = call_model(prompt)
contextual_chunks.append(f"{chunk}\n{chunk_context}")
return contextual_chunks

此函數會將每個信息塊連同整個文檔一起發送到模型,模型會生成一個簡短的上下文,以提高搜索檢索的準確性。然后,將這個上下文前置到信息塊的前面。

我們將使用fastembed4庫來為文檔的信息塊創建嵌入表示:

embedding_model = TextEmbedding()

最后,讓我們將塊及其嵌入保存在數據庫中:

def save_chunks(chunks: List[str]):
chunk_embeddings = list(embedding_model.embed(chunks))
for chunk, embedding in zip(chunks, chunk_embeddings):
result = db.execute(
"INSERT INTO chunks(document_id, text) VALUES(?, ?)", [doc_id, chunk]
)
chunk_id = result.lastrowid
db.execute(
"INSERT INTO chunk_embeddings(id, embedding) VALUES (?, ?)",
[chunk_id, serialize_float32(embedding)],
)

此函數將每個信息塊及其嵌入表示保存到數據庫中的chunks表和chunk_embeddings表中。serialize_float32函數用于將嵌入表示存儲為一種可以稍后高效檢索的格式。

檢索上下文

一旦塊及其嵌入存儲在數據庫中,我們就可以檢索給定查詢的最相關上下文。下面是實現這一點的函數:

def retrieve_context(query: str, k: int = 3, embedding_model: TextEmbedding = embedding_model) -> str:
query_embedding = list(embedding_model.embed([query]))[0]
results = db.execute(
"""
SELECT
chunk_embeddings.id,
distance,
text
FROM chunk_embeddings
LEFT JOIN chunks ON chunks.id = chunk_embeddings.id
WHERE embedding MATCH ? AND k = ?
ORDER BY distance
""",
[serialize_float32(query_embedding), k],
).fetchall()
return "\n-----\n".join([item[2] for item in results])
  1. 查詢嵌入:該函數首先使用嵌入模型將輸入查詢轉換為嵌入表示。
  2. 數據庫查詢:然后,它通過以下方式檢索與查詢嵌入表示最相似的前k個信息塊及其嵌入表示:
  3. 返回結果:將檢索到的信息塊連接成一個單獨的字符串,并用“\n—–\n”分隔以提高清晰度。

生成答案

為了生成答案,我們將系統提示符與檢索到的上下文相結合。這可確保模型提供準確且與上下文相關的響應。

系統提示為模型應如何響應設定基調和期望:

SYSTEM_PROMPT = """
You're an expert AI/ML engineer with a background in software development.
You're answering questions about technical topics and projects.
If you don't know the answer, simply state that you don't know.
Keep your answers brief and to the point. Be kind and respectful.

Use the provided context for your answers. The most relevant information is
at the top. Each piece of information is separated by ---.
"""

以下是將所有內容聯系在一起的函數:

def ask_question(query: str) -> str:
messages = [
{
"role": "system",
"content": SYSTEM_PROMPT,
},
]
context = retrieve_context(query)
prompt = dedent(
f"""
Use the following information:

```
{context}
```

to answer the question:
{query}
"""
)
return call_model(prompt, messages), context
  1. 設置系統提示:SYSTEM_PROMPT指導模型如何回答問題——鼓勵簡潔、禮貌且考慮上下文的回答。如果模型不知道答案,它會按照指示承認這一點。
  2. 檢索相關上下文:retrieve_context(query)函數從數據庫中為給定查詢檢索最相關的上下文信息塊。
  3. 創建最終提示:將檢索到的上下文插入到提示中,然后指示模型使用該信息來回答用戶的問題。
  4. 調用模型:call_model(prompt, messages)函數將提示發送到大型語言模型(LLM)并生成答案。
  5. 返回響應:該函數返回模型生成的答案以及檢索到的上下文(供審查時可選)。

要回答問題,您可以像這樣調用函數:

answer, context = ask_question("How does Contextual Retrieval improve RAG performance?")
print("Answer:", answer)
print("Context used:", context)

這既提供了答案,也提供了模型用來生成回答的上下文。

使用 RAG

現在我們可以用一些問題來測試我們的系統。讓我們先問一個關于Qwen模型的簡單問題:

query = "How many parameters does Qwen have?"
response, context = ask_question(query)
print(response)

輸出:

Qwen2.5 models are available in various sizes, with the number of parameters 
ranging from 0.5B to 72B. The specific model mentioned in the text has 32.5B
parameters, with 31.0B non-embedding parameters.

非常好,看起來模型是基于檢索到的上下文提供了準確的信息。讓我們嘗試一些技術性更強的內容:

query = "How should one deploy Qwen model on a private server?"
response, context = ask_question(query)
print(response)

輸出:

To deploy Qwen2.5 on a private server, you can use vLLM, a fast and easy-to-use 
framework for LLM inference and serving. First, install vllm>=0.4.0 using pip. Then, run the following command to build up a vLLM service: ```bash python -m vllm.entrypoints.openai.api_server --model Qwen/Qwen2.5-7B-Instruct ``` Alternatively, with vllm>=0.5.3, you can use: ```bash vllm serve Qwen/Qwen2.5-7B-Instruct ``` This will start a service that you can interact with using the OpenAI API.

這是對文檔部署部分的一個很好的總結。讓我們再嘗試一個問題:

query = "I have a RTX 4090 (24GB). Which version of the model can I run with good inference speed?"
response, context = ask_question(query)
print(response)

輸出:

Based on the provided information, the model sizes available for Qwen2.5 are 
0.5B, 1.5B, 3B, 7B, 14B, 32B, and 72B.

Considering your RTX 4090 has 24GB of memory, you can likely run the 7B or 14B
models with good inference speed. However, the 14B model might be pushing the
limits of your GPU's memory, so the 7B model would be a safer choice.

Keep in mind that the actual performance will also depend on other factors such
as your system's CPU, RAM, and the specific use case.

此信息在文檔中找不到,但該模型根據檢索到的上下文及其推理能力提供了很好的答案。

結論

您已經構建了一個 RAG 系統,該系統使用:

在繼續完善此系統的過程中,您可以考慮通過以下方式進行增強:

告訴我您打算用這個系統來構建什么!

原文鏈接:https://www.mlexpert.io/blog/rag-contextual-retrieval

熱門推薦
一個賬號試用1000+ API
助力AI無縫鏈接物理世界 · 無需多次注冊
3000+提示詞助力AI大模型
和專業工程師共享工作效率翻倍的秘密
返回頂部
上一篇
Flux 1.1 Pro的十大提示詞:最佳圖像生成創意
下一篇
GPT-4o API深度剖析:文本創作、視覺處理及函數調用詳解
国内精品久久久久影院日本,日本中文字幕视频,99久久精品99999久久,又粗又大又黄又硬又爽毛片
美女视频第一区二区三区免费观看网站| 久久一留热品黄| 一本久久a久久免费精品不卡| 在线不卡免费av| 亚洲成人av中文| 91麻豆精品国产91久久久使用方法| 亚洲欧美另类久久久精品| av电影天堂一区二区在线观看| 久久精品一区二区三区四区| 国产suv精品一区二区三区| 久久麻豆一区二区| av电影一区二区| 亚洲另类中文字| 欧美三级午夜理伦三级中视频| 午夜欧美视频在线观看| 精品三级av在线| 成人激情综合网站| 亚洲高清免费在线| 91精品国产一区二区三区| 精品亚洲国产成人av制服丝袜| 欧美激情在线看| 欧美伦理影视网| 国产精品一区免费在线观看| 国产精品三级视频| 欧美日韩久久久一区| 高清beeg欧美| 日本麻豆一区二区三区视频| 中文字幕电影一区| 欧美一区二区啪啪| av网站免费线看精品| 老司机免费视频一区二区| 亚洲精品一二三区| 久久亚洲免费视频| 欧美精品久久99| 91色乱码一区二区三区| 经典三级视频一区| 亚洲一区二区五区| 91麻豆精品国产| 91视频在线观看| 成人黄页毛片网站| 国产一区视频网站| 久久国产婷婷国产香蕉| 日韩精品一二三| 午夜国产精品一区| 一区二区三区av电影| 亚洲色图清纯唯美| 综合电影一区二区三区| 国产女同互慰高潮91漫画| 欧美精品一区二区在线播放| 91精品国产欧美日韩| 8x8x8国产精品| 欧美无砖专区一中文字| 在线精品视频小说1| 色老汉av一区二区三区| av在线综合网| gogo大胆日本视频一区| 成人午夜在线视频| 99精品视频一区| 91福利小视频| 欧美福利视频导航| 欧美成人一区二区三区片免费 | 成人黄色av电影| 久久激五月天综合精品| 黄网站免费久久| 国产成人综合亚洲网站| 成人综合婷婷国产精品久久免费| 精品一二线国产| 成人h精品动漫一区二区三区| 顶级嫩模精品视频在线看| 91在线观看免费视频| 欧美性感一类影片在线播放| 91精品中文字幕一区二区三区| 日韩一级二级三级| 国产精品超碰97尤物18| 亚洲综合精品自拍| 久久99久久99小草精品免视看| 国产suv精品一区二区6| 欧美日韩一区二区电影| 日韩欧美精品三级| 亚洲视频综合在线| 另类调教123区 | 国产福利精品一区二区| 色综合咪咪久久| 欧美成va人片在线观看| 国产精品不卡一区| 久久精品国产网站| 欧美探花视频资源| 国产精品久久久久久一区二区三区| 亚洲日韩欧美一区二区在线| 手机精品视频在线观看| 不卡的av网站| 91精品国产高清一区二区三区 | 亚洲一区二区三区在线播放| 国产盗摄精品一区二区三区在线| 在线视频你懂得一区二区三区| 精品黑人一区二区三区久久| 成人免费一区二区三区在线观看| 久久国产精品区| 欧美系列在线观看| 亚洲精品免费在线| 国产一区三区三区| 欧美www视频| 乱一区二区av| 最新国产精品久久精品| 精品一区精品二区高清| 一区二区欧美在线观看| 久久精品999| 欧美在线观看视频一区二区三区| 69堂成人精品免费视频| 精品无人码麻豆乱码1区2区| 日韩美女久久久| 国内外成人在线| 欧美日韩一区二区在线视频| 中文字幕在线不卡一区二区三区| 国产亚洲欧美日韩日本| 亚洲黄色免费网站| 国产一区91精品张津瑜| 欧美va亚洲va国产综合| 亚洲国产成人一区二区三区| 中文字幕欧美国产| 69久久99精品久久久久婷婷 | 成人自拍视频在线| 亚洲最色的网站| 久久精品噜噜噜成人av农村| 欧美性视频一区二区三区| 亚洲摸摸操操av| 欧美日韩一级二级| 香蕉成人伊视频在线观看| 欧美系列一区二区| 全国精品久久少妇| 久久久久久久综合色一本| 美女视频黄免费的久久| 国产精品国产三级国产有无不卡| 免费人成黄页网站在线一区二区| 久久69国产一区二区蜜臀| 99久久精品免费看国产| 制服丝袜成人动漫| 成人毛片在线观看| 99久久精品费精品国产一区二区| 91猫先生在线| 色综合欧美在线| av不卡在线观看| 欧美一级高清片在线观看| 91成人国产精品| 国产精品久久久久久久久快鸭| 在线播放日韩导航| 亚洲精品日韩专区silk| 国产成都精品91一区二区三| 一区二区三区资源| 成人免费毛片aaaaa**| 99久久婷婷国产综合精品电影 | 亚洲精品久久嫩草网站秘色| 日韩免费电影一区| 日本道精品一区二区三区| 国产一区二区三区| 久久美女高清视频| 狠狠网亚洲精品| 日韩免费观看2025年上映的电影| 亚洲电影视频在线| 一本一本大道香蕉久在线精品| 91丨国产丨九色丨pron| 宅男在线国产精品| 麻豆国产精品官网| 欧美精品日日鲁夜夜添| 青娱乐精品视频在线| 色噜噜狠狠成人中文综合| 亚洲免费在线看| 99精品欧美一区二区三区小说| 精品国产免费人成在线观看| 综合欧美一区二区三区| 日韩区在线观看| 欧美日韩国产精选| 欧美日韩国产在线播放网站| 色呦呦国产精品| 色综合视频在线观看| 大胆欧美人体老妇| 高清不卡一区二区| 成人精品视频一区二区三区| 国产精品77777| 成人夜色视频网站在线观看| 国产精品一区二区免费不卡| 狠狠色2019综合网| 国产精品69久久久久水密桃| 国产在线看一区| 国产精品影音先锋| 成人一级视频在线观看| youjizz久久| 欧美日韩在线精品一区二区三区激情| 欧美网站一区二区| 日韩美女一区二区三区| 国产欧美日韩三区| 亚洲日本青草视频在线怡红院| 一区二区三区在线免费播放| 日韩一区二区免费高清| 精品国产一区久久| 中文字幕一区二区三区蜜月| 亚洲成人精品一区二区| 久久精品国产99| 91污片在线观看| 久久一日本道色综合|