在本博客中,您將了解如何使用 Wea??viate、LangChain4j 和 LocalAI 實現檢索增強生成 (RAG)。此實現允許您使用自然語言詢問有關文檔的問題。享受吧!

1。簡介

上一篇中post,Weaviate 被用作矢量數據庫以執行語義搜索。使用的源文檔是兩個維基百科文檔。 唱片目錄Bruce Springsteen 錄制的歌曲列表是使用的文檔。這些文檔的有趣之處在于它們包含事實并且主要采用表格格式。這些文檔的部分內容被轉換為 Markdown,以便更好地表示。 Markdown 文件嵌入到 Weaviate 的集合中。結果是驚人的:所有提出的問題都得到了正確的答案。也就是說,返回了正確的段。您仍然需要自己提取答案,但這很容易。

但是,可以通過創建正確的提示將 Weaviate 搜索結果提供給 LLM(大型語言模型)來解決這個問題嗎? LLM 能夠提取問題的正確答案嗎?

該設置如下圖所示:

  1. 文檔嵌入并存儲在 Weaviate 中;
  2. 嵌入問題并使用 Wea??viate 執行語義搜索;
  3. Weaviate 返回語義搜索結果;
  4. 結果將添加到提示中并饋送到 LocalAI,后者使用 LangChain4j 運行 LLM;
  5. 法學碩士返回問題的答案。

weaviate 與 localAI

Weaviate 還支持 RAG,那么為什么還要使用 LocalAI和LangChain4j?遺憾的是,Weaviate 不支持與 LocalAI 集成,并且僅支持云 LLM可以使用。如果您的文檔包含敏感信息或您不想發送到基于云的 LLM 的信息,您需要運行本地 LLM,這可以使用 LocalAI 和 LangChain4j 來完成。

如果您想運行本博客中的示例,則需要閱讀上一篇博客

本博客中使用的來源可以在 GitHub 上找到。

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!)。創建了三個集合:

  1. CompilationAlbum:布魯斯·斯普林斯汀所有合輯專輯列表;
  2. 歌曲:布魯斯·斯普林斯汀的所有歌曲列表;
  3. 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。結果

運行代碼,結果如下:

  1. 《Adam Raising a Cain》最初發行于哪張專輯?
    專輯《Darkness on the Edge of Town》最初發行于 1978 年,歌曲“ Adam Raising a Cain”收錄在該專輯中。
  2. “來自新澤西州阿斯伯里帕克的問候”的最高排行榜位置是多少?在美國?
    排行榜最高位置是“來自新澤西州阿斯伯里帕克的問候”在美國是 60。
  3. 專輯《Tracks》在加拿大的最高排行榜位置是多少?
    根據提供的數據,專輯《Tracks》在加拿大的最高排行榜位置是 -。這是因為數據不包括該專輯的任何加拿大排行榜位置。
  4. 《Highway Patrolman》是哪一年發行的?
    歌曲《Highway Patrolman》于 1982 年發行。
  5. 誰制作了“all or nothin’ at all?”
    歌曲“All or Nothingth’ at All”由 Bruce Springsteen、Roy Bittan、Jon Landau 制作,和查克·普洛特金。

問題的所有答案都是正確的。最重要的工作已在 上一篇文章,以正確的方式嵌入文檔,導致找到正確的段。當提供正確的數據時,法學碩士能夠提取問題的答案。

6。注意事項

在實現過程中,我遇到了一些奇怪的行為,了解這些行為對于您何時開始實現用例非常重要。

6.1 Weaviate結果格式

Weaviate 響應包含一個 GraphQLResponse 對象,如下所示:

JSON

?

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。結果是相當驚人的。以正確的方式嵌入文檔、過濾結果并將其提供給法學碩士是一個非常強大的組合,可用于許多用例。

Comments are closed.