在本博客中,您將了解如何使用 Wea??viate、LangChain4j 和 LocalAI 實現檢索增強生成 (RAG)。此實現允許您使用自然語言詢問有關文檔的問題。享受吧!
1。簡介
在上一篇中post,Weaviate 被用作矢量數據庫以執行語義搜索。使用的源文檔是兩個維基百科文檔。 唱片目錄和Bruce Springsteen 錄制的歌曲列表是使用的文檔。這些文檔的有趣之處在于它們包含事實并且主要采用表格格式。這些文檔的部分內容被轉換為 Markdown,以便更好地表示。 Markdown 文件嵌入到 Weaviate 的集合中。結果是驚人的:所有提出的問題都得到了正確的答案。也就是說,返回了正確的段。您仍然需要自己提取答案,但這很容易。
但是,可以通過創建正確的提示將 Weaviate 搜索結果提供給 LLM(大型語言模型)來解決這個問題嗎? LLM 能夠提取問題的正確答案嗎?
該設置如下圖所示:
- 文檔嵌入并存儲在 Weaviate 中;
- 嵌入問題并使用 Wea??viate 執行語義搜索;
- Weaviate 返回語義搜索結果;
- 結果將添加到提示中并饋送到 LocalAI,后者使用 LangChain4j 運行 LLM;
- 法學碩士返回問題的答案。
Weaviate 還支持 RAG,那么為什么還要使用 LocalAI和LangChain4j?遺憾的是,Weaviate 不支持與 LocalAI 集成,并且僅支持云 LLM可以使用。如果您的文檔包含敏感信息或您不想發送到基于云的 LLM 的信息,您需要運行本地 LLM,這可以使用 LocalAI 和 LangChain4j 來完成。
如果您想運行本博客中的示例,則需要閱讀上一篇博客。
本博客中使用的來源可以在 GitHub 上找到。 p>
2。先決條件
此博客的先決條件是:
- 嵌入和向量存儲的基本知識;
- Java基礎知識,使用Java 21;
- Docker 基礎知識;
- LangChain4j基礎知識;
- 您需要 Weaviate 并且需要嵌入文檔,請參閱上一篇博客介紹了如何執行此操作;
- 如果您想運行示例,則需要 LocalAI,請參閱上一篇博客 了解如何利用 LocalAI。本博客使用的是 2.2.0 版本。
- 如果您想了解有關 RAG 的更多信息,請閱讀此博客.
3。創建設置
開始之前,需要進行一些設置。
3.1 設置 LocalAI
LocalAI 必須正在運行并配置。博客中解釋了如何執行此操作本地運行LLM:分步-步驟指南。
3.2 設置 Weaviate
Weaviate 必須啟動。與 Weaviate 博客的唯一區別是您將在端口 8081 而不是端口 8080 上運行它。這是因為 LocalAI 已經在端口 8080 上運行。
從存儲庫的根目錄啟動撰寫文件。
?
$ docker compose -f docker/compose-embed-8081.yaml
運行類 EmbedMarkdown 以嵌入文檔(將端口更改為 8081!)。創建了三個集合:
- CompilationAlbum:布魯斯·斯普林斯汀所有合輯專輯列表;
- 歌曲:布魯斯·斯普林斯汀的所有歌曲列表;
- StudioAlbum:Bruce Springsteen 所有錄音室專輯的列表。
4。實施RAG
4.1 語義搜索
實現的第一部分基于類 SearchCollectionNearText。這里假設您知道要在哪個集合(參數className)中搜索。
在上一篇中發布后,您注意到嚴格來說,您不需要知道要搜索哪個集合。然而,此時,它使實現變得更容易一些,并且結果保持不變。
代碼將接受問題,并在 NearTextArgument 的幫助下嵌入問題。 Weaviate 的 GraphQL API 用于執行搜索。
?
private static String createPrompt(String Question, String inputData, String extraInstruction) {
return "回答以下問題:" + 問題 + "\n" +
額外指令 + "\n" +
"使用以下數據回答問題:" + inputData;
}
4.3 使用法學碩士
最后要做的是將提示提供給 LLM 并將問題和答案打印到控制臺。
?
private static void AskQuestion(String className, Field[] fields, String Question, String extraInstruction) {
...
ChatLanguageModel 模型 = LocalAiChatModel.builder()
.baseUrl("http://localhost:8080")
.modelName("lunademo")
.溫度(0.0)
。建造();
String Answer = model.generate(createPrompt(question, result.getResult().getData().toString(), extraInstruction));
System.out.println(問題);
System.out.println(答案);
}
4.4 問題
要問的問題與之前的帖子相同。他們將調用上面的代碼。
?
public static void main(String[] args) {
AskQuestion(Song.NAME, Song.getFields(), "最初發行的《亞當舉起凱恩》是在哪張專輯上?", "");
AskQuestion(StudioAlbum.NAME, StudioAlbum.getFields(), "《來自新澤西州阿斯伯里帕克的問候》在美國的最高排行榜位置是多少?", "");
AskQuestion(CompilationAlbum.NAME, CompilationAlbum.getFields(), "專輯\"tracks\"在加拿大的最高排行榜位置是多少?", "");
AskQuestion(Song.NAME, Song.getFields(), "《公路巡警》是哪一年發行的?", "");
AskQuestion(Song.NAME, Song.getFields(), "誰創作了\"全有或全無?\"", "");
}
完整源碼可查看此處。
5。結果
運行代碼,結果如下:
- 《Adam Raising a Cain》最初發行于哪張專輯?
專輯《Darkness on the Edge of Town》最初發行于 1978 年,歌曲“ Adam Raising a Cain”收錄在該專輯中。 - “來自新澤西州阿斯伯里帕克的問候”的最高排行榜位置是多少?在美國?
排行榜最高位置是“來自新澤西州阿斯伯里帕克的問候”在美國是 60。 - 專輯《Tracks》在加拿大的最高排行榜位置是多少?
根據提供的數據,專輯《Tracks》在加拿大的最高排行榜位置是 -。這是因為數據不包括該專輯的任何加拿大排行榜位置。 - 《Highway Patrolman》是哪一年發行的?
歌曲《Highway Patrolman》于 1982 年發行。 - 誰制作了“all or nothin’ at all?”
歌曲“All or Nothingth’ at All”由 Bruce Springsteen、Roy Bittan、Jon Landau 制作,和查克·普洛特金。
問題的所有答案都是正確的。最重要的工作已在 上一篇文章,以正確的方式嵌入文檔,導致找到正確的段。當提供正確的數據時,法學碩士能夠提取問題的答案。
6。注意事項
在實現過程中,我遇到了一些奇怪的行為,了解這些行為對于您何時開始實現用例非常重要。
6.1 Weaviate結果格式
Weaviate 響應包含一個 GraphQLResponse 對象,如下所示:
?
GraphQLResponse(
數據={
獲取={
歌曲=[
{_additional={確定性=0.7534831166267395,距離=0.49303377},
OriginalRelease=城鎮邊緣的黑暗,
制片人=喬恩·蘭道、布魯斯·斯普林斯汀、史蒂文·范·贊特(助理)、
歌曲=“亞當養育了該隱”,作者=布魯斯·斯普林斯汀,年份=1978}
]
}
},
錯誤=空)
在代碼中,數據部分用于添加到提示中。
?
字符串答案 = model.generate(createPrompt(question, result.getResult().getData().toString(), extraInstruction));上一篇>
當您將響應按原樣添加到提示時會發生什么?
字符串答案 = model.generate(createPrompt(question, result.getResult().toString(), extraInstruction));
運行代碼會返回問題 3 的以下錯誤答案以及問題 4 的一些不必要的附加信息。其他問題均已正確回答。
- 專輯《Tracks》在加拿大的最高排行榜位置是多少?
根據提供的數據,專輯《Tracks》在加拿大的最高排行榜位置是 50。 - 《高速公路巡警》是哪一年發布的?
根據提供的 GraphQLResponse,《高速公路巡警》于 1982 年發布。
誰制作了“所有或者什么都沒有?”
6.2 提示格式
該代碼包含向提示添加額外指令的功能。您可能已經注意到,沒有使用此功能。讓我們看看當您從提示中刪除此內容時會發生什么。 createPrompt 方法如下(我沒有刪除所有內容,因此只需要進行較小的代碼更改)。
?
private static String createPrompt(String Question, String inputData, String extraInstruction) {
return "回答以下問題:" + 問題 + "\n" +
"使用以下數據回答問題:" + inputData;
}
運行代碼會為問題 3 的答案添加一些額外的信息,這并不完全正確。這張專輯在美國、英國、德國和瑞典的排行榜上的位置是正確的。說這張專輯進入英國和美國排行榜前十名是不正確的。所有其他問題均已正確回答。
- 專輯《Tracks》在加拿大的最高排行榜位置是多少?
根據提供的數據,專輯《Tracks》在加拿大的最高排行榜位置沒有指定。該數據僅包括美國、英國、德國和瑞典等其他國家的圖表位置。不過,這張專輯確實進入了英國和美國排行榜前十名。
使用法學碩士時它仍然有點脆弱。你不能總是相信它給出的答案。相應地改變提示似乎可以最大限度地減少法學碩士的幻覺。因此,收集用戶的反饋非常重要,以便確定法學碩士何時出現幻覺。這樣,您將能夠改善對用戶的響應。一個有趣的 博客是由 Fiddler 編寫的,它解決了此類問題。
7。結論
在本博客中,您學習了如何使用 Wea??viate、LangChain4j 和 LocalAI 實現 RAG。結果是相當驚人的。以正確的方式嵌入文檔、過濾結果并將其提供給法學碩士是一個非常強大的組合,可用于許多用例。

