قم بدمج قوة نماذج اللغات الكبيرة (LLM) في تطبيق Go الخاص بك.
يهدف هذا المشروع إلى تجريد الكثير من السباكة (نص مجاني للبيانات المنظمة، والذاكرة السياقية، وتغليف الأدوات، ومنطق إعادة المحاولة، وما إلى ذلك) حتى تتمكن من التركيز على منطق الأعمال الخاص بوكيلك.
الرسم البياني LR
إدخال الرسم البياني الفرعي
أ[الإدخال المنظم] --> ب[مهمة مجمعة]
نهاية
وكيل قائم على LLM
C[قالب المهمة] --> B[مهمة مجمعة]
ب --> د ((الوكيل))
د--"الاستدلال"--> د
D --"الإجراء"--> E[البيئة]
هـ --"الملاحظة"--> د
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. لا يتم حاليًا دعم سوى واجهة برمجة تطبيقات إكمال دردشة GPT الخاصة بـ OpenAI.
الأدوات التي يمكنها تزويد الوكلاء بالقدرة على تنفيذ الإجراءات التي تتفاعل مع العالم الخارجي. الأدوات المتوفرة حاليا هي:
PythonREPL
- أداة تسمح للوكلاء بتنفيذ كود Python في REPL.IsolatedPythonREPL
- أداة تسمح للوكلاء بتنفيذ كود Python في REPL، ولكن في حاوية Docker.BashTerminal
- أداة تسمح للوكلاء بتنفيذ أوامر bash في المحطة الطرفية.GoogleSearch
- أداة تسمح للوكلاء بالبحث في Google.WebpageSummary
- أداة تعتمد على LLM تسمح للوكلاء بالحصول على ملخص لصفحة الويب.WolframAlpha
- أداة تسمح للوكلاء بالاستعلام عن واجهة برمجة تطبيقات الإجابة القصيرة الخاصة بـ WolframAlpha.KeyValueStore
- أداة لتخزين واسترجاع المعلومات. يمكن للوكيل استخدام هذه الأداة لإعادة استخدام أجزاء طويلة من المعلومات حسب المرجع، وإزالة التكرار وبالتالي تقليل حجم السياق.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 ])
}