Integrieren Sie die Leistungsfähigkeit großer Sprachmodelle (LLM) in Ihre Go-Anwendung.
Dieses Projekt zielt darauf ab, einen Großteil des Aufwands zu abstrahieren (Freitext in strukturierte Daten, Kontextspeicher, Tool-Wrapping, Wiederholungslogik usw.), damit Sie sich auf die Geschäftslogik Ihres Agenten konzentrieren können.
Grafik LR
Untergraph Eingabe
A[Strukturierte Eingabe] -> B[Kompilierte Aufgabe]
Ende
Unterabschnitt LLM-basierter Agent
C[Aufgabenvorlage] -> B[Kompilierte Aufgabe]
B -> D((Agent))
D – „Begründung“ -> D
D – „Aktion“ -> E[Umgebung]
E – „Beobachtung“ -> D
D --"Antwort"--> G[Ausgabevalidatoren]
G -> D
Ende
Untergraph-Ausgabe
G --"Antwort"--> F[Strukturierte Ausgabe]
Ende
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." ,
})
...
}
Notiz
Interessante Tatsache: Die Datei
tools/bash_test.go
wurde von genau diesem Agenten geschrieben und hat dabei geholfen, einen Fehler zu finden!
Anschlüsse für LLM-Engines. Derzeit wird nur die GPT-Chat-Abschluss-API von OpenAI unterstützt.
Tools, die Agenten die Möglichkeit geben können, Aktionen auszuführen, indem sie mit der Außenwelt interagieren. Derzeit verfügbare Tools sind:
PythonREPL
– ein Tool, das es Agenten ermöglicht, Python-Code in einer REPL auszuführen.IsolatedPythonREPL
– ein Tool, das es Agenten ermöglicht, Python-Code in einer REPL, aber in einem Docker-Container auszuführen.BashTerminal
– ein Tool, das es Agenten ermöglicht, Bash-Befehle in einem Terminal auszuführen.GoogleSearch
– ein Tool, mit dem Agenten Google durchsuchen können.WebpageSummary
– ein LLM-basiertes Tool, mit dem Agenten eine Zusammenfassung einer Webseite abrufen können.WolframAlpha
– ein Tool, mit dem Agenten die Kurzantwort-API von WolframAlpha abfragen können.KeyValueStore
– ein Tool zum Speichern und Abrufen von Informationen. Der Agent kann dieses Tool verwenden, um lange Informationsteile per Referenz wiederzuverwenden, wodurch Duplikate vermieden und somit die Kontextgröße reduziert werden.AskUser
– ein Interaktivitätstool, mit dem der Agent bei Bedarf einen menschlichen Bediener um Klarstellungen bitten kann.JSONAutoFixer
– ein Meta-Tool, das standardmäßig aktiviert ist. Wenn die Argumente eines Tools in einer Form bereitgestellt werden, die kein gültiges JSON ist, versucht dieses Tool, die Nutzlast mithilfe einer separaten LLM-Kette zu reparieren.GenericAgentTool
– ermöglicht es einem Agenten, einen anderen Agenten mit vordefinierten Tools auszuführen, ihn dynamisch mit seiner Aufgabe und Eingabe zu versorgen und seine endgültige Antwort zu sammeln.Warnung
Mit den
BashTerminal
und regulärenPythonREPL
Tools kann der Agent beliebige Befehle auf Ihrem Computer ausführen. Die Verwendung erfolgt auf eigenes Risiko. Es kann eine gute Idee sein, die integrierte Unterstützung für Aktionsbestätigungsrückrufe zu verwenden (siehe dieWithActionConfirmation
-Methode für denChainAgent
-Typ).
go-llm
Tools unterstützen die neue OpenAI-Funktionsaufrufschnittstelle transparent für Modellvarianten, die über diese Funktion verfügen.
Ein Speichersystem, das es Agenten ermöglicht, Informationen zu speichern und abzurufen. Derzeit verfügbare Speichersysteme sind:
BufferMemory
– stellt jedem Schritt des Agenten einen festen Puffer der letzten Nachrichten aus dem Konversationsverlauf zur Verfügung.SummarisedMemory
– stellt jedem Schritt des Agenten eine Zusammenfassung des Gesprächsverlaufs bereit, unterstützt durch ein LLM.Agenten sind die Hauptkomponente der Bibliothek. Agenten können komplexe Aufgaben ausführen, die iterative Interaktionen mit der Außenwelt beinhalten.
Eine Sammlung vorgefertigter Agenten, die problemlos in Ihre Anwendung integriert werden können.
Eine Sammlung von Evaluierungstools für Agenten und Engines.
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 ])
}