ผสานรวมพลังของโมเดลภาษาขนาดใหญ่ (LLM) เข้ากับแอปพลิเคชัน Go ของคุณ
โปรเจ็กต์นี้มีจุดมุ่งหมายเพื่อสรุปการเชื่อมต่อส่วนใหญ่ (ข้อความอิสระไปยังข้อมูลที่มีโครงสร้าง หน่วยความจำตามบริบท การห่อเครื่องมือ ตรรกะในการลองใหม่ ฯลฯ) เพื่อให้คุณสามารถมุ่งเน้นไปที่ตรรกะทางธุรกิจของตัวแทนของคุณ
กราฟ LR
อินพุตกราฟย่อย
A[อินพุตที่มีโครงสร้าง] --> B[งานที่คอมไพล์แล้ว]
จบ
ตัวแทนที่ใช้ LLM กราฟย่อย
C [เทมเพลตงาน] -> B [งานที่คอมไพล์แล้ว]
B --> D((ตัวแทน))
D --"การใช้เหตุผล"-->D
D --"การกระทำ"--> E[สิ่งแวดล้อม]
E --"การสังเกต" --> D
D --"คำตอบ"--> G[เครื่องมือตรวจสอบผลลัพธ์]
จี --> ดี
จบ
เอาท์พุทกราฟย่อย
G --"คำตอบ"--> F[เอาต์พุตที่มีโครงสร้าง]
จบ
package main
import (
"encoding/json"
"fmt"
"os"
"github.com/natexcvi/go-llm/agents"
"github.com/natexcvi/go-llm/engines"
"github.com/natexcvi/go-llm/memory"
"github.com/natexcvi/go-llm/tools"
)
type CodeBaseRefactorRequest struct {
Dir string
Goal string
}
func ( req CodeBaseRefactorRequest ) Encode () string {
return fmt . Sprintf ( `{"dir": "%s", "goal": "%s"}` , req . Dir , req . Goal )
}
func ( req CodeBaseRefactorRequest ) Schema () string {
return `{"dir": "path to code base", "goal": "refactoring goal"}`
}
type CodeBaseRefactorResponse struct {
RefactoredFiles map [ string ] string `json:"refactored_files"`
}
func ( resp CodeBaseRefactorResponse ) Encode () string {
marshalled , err := json . Marshal ( resp . RefactoredFiles )
if err != nil {
panic ( err )
}
return string ( marshalled )
}
func ( resp CodeBaseRefactorResponse ) Schema () string {
return `{"refactored_files": {"path": "description of changes"}}`
}
func main () {
task := & agents. Task [ CodeBaseRefactorRequest , CodeBaseRefactorResponse ]{
Description : "You will be given access to a code base, and instructions for refactoring." +
"your task is to refactor the code base to meet the given goal." ,
Examples : []agents. Example [ CodeBaseRefactorRequest , CodeBaseRefactorResponse ]{
{
Input : CodeBaseRefactorRequest {
Dir : "/Users/nate/code/base" ,
Goal : "Handle errors gracefully" ,
},
Answer : CodeBaseRefactorResponse {
RefactoredFiles : map [ string ] string {
"/Users/nate/code/base/main.py" : "added try/except block" ,
},
},
IntermediarySteps : [] * engines. ChatMessage {
( & agents. ChainAgentThought {
Content : "I should scan the code base for functions that might error." ,
}). Encode ( engine ),
( & agents. ChainAgentAction {
Tool : tools . NewBashTerminal (),
Args : json . RawMessage ( `{"command": "ls /Users/nate/code/base"}` ),
}). Encode ( engine ),
( & agents. ChainAgentObservation {
Content : "main.py" ,
ToolName : tools . NewBashTerminal (). Name (),
}). Encode ( engine ),
( & agents. ChainAgentThought {
Content : "Now I should read the code file." ,
}). Encode ( engine ),
( & agents. ChainAgentAction {
Tool : tools . NewBashTerminal (),
Args : json . RawMessage ( `{"command": "cat /Users/nate/code/base/main.py"}` ),
}). Encode ( engine ),
( & agents. ChainAgentObservation {
Content : "def main(): n t func_that_might_error()" ,
ToolName : tools . NewBashTerminal (). Name (),
}). Encode ( engine ),
( & agents. ChainAgentThought {
Content : "I should refactor the code to handle errors gracefully." ,
}). Encode ( engine ),
( & agents. ChainAgentAction {
Tool : tools . NewBashTerminal (),
Args : json . RawMessage ( `{"command": "echo 'def main():nttry:nttfunc_that_might_error()ntexcept Exception as e:nttprint("Error: %s", e)' > /Users/nate/code/base/main.py"}` ),
}). Encode ( engine ),
},
},
},
AnswerParser : func ( msg string ) ( CodeBaseRefactorResponse , error ) {
var res CodeBaseRefactorResponse
if err := json . Unmarshal ([] byte ( msg ), & res ); err != nil {
return CodeBaseRefactorResponse {}, err
}
return res , nil
},
}
agent := agents . NewChainAgent ( engines . NewGPTEngine ( os . Getenv ( "OPENAI_TOKEN" ), "gpt-3.5-turbo-0613" ), task , memory . NewBufferedMemory ( 0 )). WithMaxSolutionAttempts ( 12 ). WithTools ( tools . NewPythonREPL (), tools . NewBashTerminal ())
res , err := agent . Run ( CodeBaseRefactorRequest {
Dir : "/Users/nate/Git/go-llm/tools" ,
Goal : "Write unit tests for the bash.go file, following the example of python_repl_test.go." ,
})
...
}
บันทึก
เรื่องน่ารู้: ไฟล์
tools/bash_test.go
เขียนโดยเอเจนต์คนนี้ และช่วยค้นหาจุดบกพร่อง!
เชื่อมต่อกับเครื่องยนต์ LLM ปัจจุบันรองรับเฉพาะ API การจบการแชท GPT ของ OpenAI เท่านั้น
เครื่องมือที่ช่วยให้ตัวแทนสามารถดำเนินการโต้ตอบกับโลกภายนอกได้ เครื่องมือที่มีอยู่ในปัจจุบันคือ:
PythonREPL
- เครื่องมือที่ช่วยให้เอเจนต์สามารถรันโค้ด Python ใน REPLIsolatedPythonREPL
- เครื่องมือที่ช่วยให้เอเจนต์สามารถรันโค้ด Python ใน REPL แต่ในคอนเทนเนอร์ DockerBashTerminal
- เครื่องมือที่ช่วยให้เอเจนต์สามารถรันคำสั่ง bash ในเทอร์มินัลได้GoogleSearch
- เครื่องมือที่ช่วยให้ตัวแทนสามารถค้นหา Google ได้WebpageSummary
- เครื่องมือที่ใช้ LLM ซึ่งช่วยให้ตัวแทนสามารถรับข้อมูลสรุปของเว็บเพจได้WolframAlpha
- เครื่องมือที่ช่วยให้ตัวแทนสามารถสืบค้น API คำตอบสั้น ๆ ของ WolframAlphaKeyValueStore
- เครื่องมือสำหรับจัดเก็บและดึงข้อมูล เอเจนต์สามารถใช้เครื่องมือนี้เพื่อนำข้อมูลขนาดยาวกลับมาใช้ใหม่โดยการอ้างอิง ลบความซ้ำซ้อน และลดขนาดบริบทAskUser
- เครื่องมือโต้ตอบที่ช่วยให้ตัวแทนถามผู้ปฏิบัติงานที่เป็นมนุษย์เพื่อขอคำชี้แจงเมื่อจำเป็นJSONAutoFixer
- เครื่องมือเมตาที่เปิดใช้งานตามค่าเริ่มต้น เมื่อมีการระบุอาร์กิวเมนต์ของเครื่องมือใดๆ ในรูปแบบที่ไม่ถูกต้อง JSON เครื่องมือนี้จะพยายามแก้ไขเพย์โหลดโดยใช้สายโซ่ LLM ที่แยกต่างหากGenericAgentTool
- อนุญาตให้ตัวแทนเรียกใช้ตัวแทนอื่นด้วยเครื่องมือที่กำหนดไว้ล่วงหน้า มอบงานและอินพุตแบบไดนามิกให้กับตัวแทน และรวบรวมคำตอบสุดท้ายคำเตือน
เครื่องมือ
BashTerminal
และPythonREPL
ทั่วไปช่วยให้เอเจนต์รันคำสั่งที่กำหนดเองบนเครื่องของคุณได้ โดยคุณต้องรับความเสี่ยงเอง อาจเป็นความคิดที่ดีที่จะใช้การสนับสนุนในตัวสำหรับการโทรกลับยืนยันการดำเนินการ (ดูวิธีWithActionConfirmation
ในประเภทChainAgent
)
เครื่องมือ go-llm
รองรับอินเทอร์เฟซการเรียกฟังก์ชัน OpenAI ใหม่อย่างโปร่งใส สำหรับรุ่นย่อยที่มีคุณสมบัตินี้
ระบบหน่วยความจำที่ช่วยให้ตัวแทนสามารถจัดเก็บและเรียกค้นข้อมูลได้ ระบบหน่วยความจำที่มีอยู่ในปัจจุบันคือ:
BufferMemory
- ซึ่งจัดเตรียมบัฟเฟอร์คงที่สำหรับข้อความล่าสุดจากประวัติการสนทนาให้กับแต่ละขั้นตอนของตัวแทนSummarisedMemory
- ซึ่งให้ข้อมูลสรุปประวัติการสนทนาแก่แต่ละขั้นตอนของตัวแทน ซึ่งขับเคลื่อนโดย LLMตัวแทนเป็นองค์ประกอบหลักของห้องสมุด เจ้าหน้าที่สามารถทำงานที่ซับซ้อนที่เกี่ยวข้องกับการโต้ตอบซ้ำกับโลกภายนอกได้
คอลเลกชันตัวแทนสำเร็จรูปที่สามารถรวมเข้ากับแอปพลิเคชันของคุณได้อย่างง่ายดาย
ชุดเครื่องมือประเมินผลสำหรับตัวแทนและเครื่องยนต์
package main
import (
"fmt"
"os"
"github.com/natexcvi/go-llm/engines"
"github.com/natexcvi/go-llm/evaluation"
)
func goodness ( _ * engines. ChatPrompt , _ * engines. ChatMessage , err error ) float64 {
if err != nil {
return 0
}
return 1
}
func main () {
engine := engines . NewGPTEngine ( os . Getenv ( "OPENAI_TOKEN" ), "gpt-3.5-turbo-0613" )
engineRunner := evaluation . NewLLMRunner ( engine )
evaluator := evaluation . NewEvaluator ( engineRunner , & evaluation. Options [ * engines. ChatPrompt , * engines. ChatMessage ]{
GoodnessFunction : goodness ,
Repetitions : 5 ,
})
testPack := [] * engines. ChatPrompt {
{
History : [] * engines. ChatMessage {
{
Text : "Hello, how are you?" ,
},
{
Text : "I'm trying to understand how this works." ,
},
},
},
{
History : [] * engines. ChatMessage {
{
Text : "Could you please explain it to me?" ,
},
},
},
}
results := evaluator . Evaluate ( testPack )
fmt . Println ( "Goodness level of the first prompt:" , results [ 0 ])
fmt . Println ( "Goodness level of the second prompt:" , results [ 1 ])
}