自定義RAG工作流:在IDE中結合RAG編排,構建可信的編碼智慧體

構建編碼智慧體並非一件容易的事。結合我們在 AutoDev、ArchGuard Co-mate、ChocoBuilder 等智慧體專案的經驗,我們開始思考在 Shire 語言中提供一種新的 RAG 工作流。結合我們先前構建的 IDE 基礎設施(程式碼生成、程式碼校驗、程式碼執行等介面),現在你可以構建出更可信的編碼智慧體。

TL;DR(太長不看)版

現在,你可以使用 Shire + 自定義的 RAG 流程智慧體編排。如下程式碼所示,你可以
  • 使用自己編寫的 prompt 與 IDE 介面來獲取程式碼資料
  • 對程式碼進行向量化、檢索與普通的程式碼搜尋
  • 將引數傳遞給下一個流程( execute 函式)
  1. ---
  2. name:"Search"
  3. variables:
  4. "placeholder":/.*.java/{ splitting | embedding }
  5. "input":"部落格建立流程"
  6. afterStreaming:{
  7. case condition {
  8. default{ searching($output)| execute("SummaryQuestion.shire", $output, $input)}
  9. }
  10. }
  11. ---
  12. xxx
  13. User: $input
  14. Response:
再結合我們的程式碼校驗、程式碼執行等功能,你可以構建出一個完整、可信的編碼智慧體。
詳細見:https://shire.phodal.com/workflow/rag-flow.html

基礎 Shire 能力:Pattern Action 與程式碼可信函式

Shire 提供了一種簡便 AI 編碼智慧體語言,能夠讓大型語言模型(LLM)與控制整合開發環境(IDE)之間自由對話,以實現自動化程式設計。
簡單來說,你可以透過 Shire 去:
  • 呼叫封裝的 IDE API,以生成 prompt 所需的資料。在 Shire 中,資料在 prompt 中以變數的形式存在。
  • 定義在 IDE 中的行為,如何觸發、如何執行,以及如何處理結果。
  • 定義簡單的資料流處理,如何處理資料、如何儲存資料。
因此,你可以透過 Shire 作為中間語言,訪問自己的 IDE 資料,生成與 AI 模型對話的 prompt,以實現自動化程式設計。

Shire RAG 基礎:Pattern Action 構建資料流

在先前的 Shire 中,你可以透過 variables 來自定義你的 Pattern Action,以從 IDE 中獲取資料。如下所示:
  1. ---
  2. variables:
  3. "logContent":/.*.java/{ grep("error.log")| head }
  4. ---
  5. 檢查使用者的程式碼是否有問題:$logContent
在這個例子中,我們定義了一個變數 logContent,它的值是從所有 *.java 檔案中檢索 error.log 的結果。最後,將結果傳送給 LLM,由 AI 來進行對應的處理。
詳細見:https://shire.phodal.com/shire/shire-custom-variable.html#variable-pattern-action

Shire RAG 基礎:程式碼可信校驗

Shire 的程式碼校驗是在 Shire 生命週期的 onStreamingDone 中執行的,即在 Streaming 完成後透過一系列的後處理器對生成的內容進行處理。在現有的版本中,支援三個函式:
  • parseCode 將文字解析為程式碼塊。
  • verifyCode 檢查程式碼錯誤或 PSI 問題。
  • runCode 執行生成的文字程式碼。
因此,你可以採用如下的方式來處理 LLM 生成的程式碼:
  1. ---
  2. onStreamingEnd:{ parseCode | saveFile | openFile | verifyCode | runCode }
  3. ---
  4. 生成一個 python hello world,使用 markdown block 返回
當你啟動 Shire 指令的那一刻,一場精心編排的編碼舞蹈便悄然展開。首先,Shire RAG 工作流會呼叫 Language Model(LLM),這個強大的語言模型迅速進入狀態,開始生成一段 Python 語言的經典之作——Hello World 程式碼塊。
  • 生成的程式碼塊接下來會透過 saveFile 功能,被小心翼翼地儲存到指定的檔案中。
  • 為了確保這段程式碼的準確性和可靠性,Shire RAG 工作流會啟動 verifyCode 函式,進行嚴格的語法校驗。
  • 一旦透過語法校驗,接下來就是激動人心的時刻——透過 runCode 函式來執行這段程式碼。
這一刻,程式碼彷彿被賦予了生命,它將在 IDE 中綻放出耀眼的光芒,將 "Hello, World!" 這句問候語,優雅地展現在我們的眼前。
詳細見:https://shire.phodal.com/lifecycle/on-streaming-done.html

Shire RAG 基礎:Index 與 Query

結合我們先前的 RAGScript 與 RAG 專案經驗,只需要透過簡單的函式,就可以實現程式碼的檢索與查詢。如下所示:
  1. ---
  2. name:"Search"
  3. variables:
  4. "testTemplate":/.*.kt/{ splitting | embedding | searching("blog")}
  5. ---
  6. $testTemplate
在這個例子中,我們定義了一個變數 testTemplate,它的值是從所有 *.kt 檔案中檢索 blog 的結果。隨後,你就可以將結果傳送給 LLM,由 AI 來進行對應的處理。

Shire RAG Flow:解釋程式碼示例

當我們使用領先 AI IDE (如 AutoDev VSCode 版本)的業務知識解釋功能時,通常會分為 3~5 個步驟:
  1. 查詢轉換。將使用者的問題,轉換或者擴充套件(query expansion)為某種形式的查詢語句。有的是關鍵詞、有的是是假設性程式碼。
  2. 資訊檢索。隨後,將查詢的結果結合本地的資料(文字、向量等)進行檢索,以獲取到相關的資訊。
  3. 重新排序。對檢索到的資訊進行排序、解釋等處理,以生成對應的結果。
  4. 內容總結。最後,將結果發給 LLM,由 AI 來進行對應的處理。
根據不同的上下文或者業務需求,這個流程可能會有所不同。但是,基本的流程是一樣的。而在使用 Shire 開發時,由於我們只需要和 LLM 互動兩次,所以只需要兩步:
  1. 將使用者的問題發給 LLM,並進行檢索
  2. 由 LLM 來總結上一步的結果
儘管過程簡化,但是如何抽象中這種原子能力,對 Shire 提出了更高的要求。因此,在這裡我們也是作為一個 PoC 來進行展示,我們將在後續的版本中,提供更多的能力。

步驟 1:使用 Shire 自定義程式碼檢索

有了上述的基礎,我們可以開始構建一個 RAG 流程。如下所示,我們可以:
  1. ---
  2. name:"Search"
  3. variables:
  4. "placeholder":/.*.java/{ splitting | embedding }
  5. "lang":"java"
  6. "input":"部落格建立流程"
  7. afterStreaming:{
  8. case condition {
  9. default{ searching($output)| execute("summary.shire", $input, $output)}
  10. }
  11. }
  12. ---
  13. []:這裡寫一些CoT相關的指令
在這個例子中,我們定義了一個變數 placeholder,它的值是從所有 *.java 檔案中檢索 部落格建立流程 的結果。由於,預設情況下,會將 embedding 的結果儲存在記憶體中,所以在 afterStreaming 時,我們就可以直接拿來使用。
afterStreaming 會在 Streaming 完成後執行,這裡我們使用 searching 函式結合上一步的結果,來進行檢索。最後,將結果傳送給下一個流程。

步驟 2:使用 LLM 進行總結

在第一步中,我們決定了下一個指令的名稱為 summary.shire,並且傳遞了兩個引數: $input 和 $output。在這個流程中,我們可以直接使用這兩個引數:
  1. []:這裡寫一些 prompt
  2. 程式碼資訊如下:
  3. $output
  4. 使用者的問題: $input
隨後,Shire 會自動執行這個指令,並將結果返回給使用者,即對問題的總結。
詳細見:https://shire.phodal.com/workflow/rag-flow.html

Shire RAG 工作流的實現

實現 Shire RAG 工作流,並非一件容易的事。我們在人力有限的情況下,需要經過大量的調研和試驗,以及場景驗證。我們調研了被廣泛採用的編碼 RAG 工具, 以探索更多的可能性。我們還嘗試了不同的編碼智慧體的實現方式,以及不同的編碼智慧體的實現方式。

Shire RAG 技術棧

Shire RAG 工作流主要使用的技術棧如下:
  • 推理框架:ONNX Runtime
  • Embedding 模型:Sentence Transformers all-MiniLM-L6-v2
  • 相似度演算法:Jaccard similarity(預設)
  • 資料儲存:記憶體(預設)、本地檔案(專案目錄)、未來:SQLite
  • Tokenizer:HF Tokenizer
而除了 RAG 部分,基於 NLP 與搜尋的傳統檢索方式也是支援的,諸如於:
  • similarCode 變數:透過 Jaccard 等演算法,來檢索相似的程式碼。
  • similarTestCase 變數:透過 TF-IDF 來檢索相似的測試用例。
我們嘗試將更多的演算法與技術整合到 Shire RAG 工作流中,以提供更多的能力。

文件支援

基於我們構建的 LLM 開發框架 ChocoBuilder,現在可以支援:
  • Office 文件:docx, pptx, xlsx 檔案
  • PDF 文件
  • 非二進位制檔案
  • IDE 支援語言程式碼檔案
  • IDE 不支援語言程式碼檔案
當然,現有版本的程式碼拆分機制還不夠完善,我們會在後續版本中提供更多的支援。

下一步

我們現在的版本只能滿足一些簡單的需求,但是在實際的開發中,我們還需要更多的能力。因此,我們會在後續版本中提供更多的能力:
  • 支援更多的儲存方式,如向量資料庫。
  • 支援對結果進行重排,如 LIM、LLM Rerank 等。
  • 支援更多的檢索方式,如 BM25+、BM42 等。
  • ……
詳細見:https://github.com/phodal/shire


相關文章