Intégrez la puissance des grands modèles de langage (LLM) dans votre application Go.
Ce projet vise à faire abstraction d'une grande partie de la plomberie (texte libre vers données structurées, mémoire contextuelle, emballage d'outils, logique de nouvelle tentative, etc.) afin que vous puissiez vous concentrer sur la logique métier de votre agent.
graphique LR
Entrée du sous-graphe
A[Entrée structurée] --> B[Tâche compilée]
fin
agent basé sur LLM subgraph
C[Modèle de tâche] --> B[Tâche compilée]
B --> D((Agent))
D --"Raisonnement" -> D
D --"Action"--> E[Environnement]
E --"Observation"--> D
D --"Réponse"--> G[Validateurs de sortie]
G --> D
fin
Sortie du sous-graphe
G --"Réponse"--> F[Sortie structurée]
fin
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." ,
})
...
}
Note
Fait amusant : le fichier
tools/bash_test.go
a été écrit par cet agent et a aidé à trouver un bug !
Connecteurs aux moteurs LLM. Actuellement, seule l'API de complétion de chat GPT d'OpenAI est prise en charge.
Des outils qui peuvent fournir aux agents la possibilité d'effectuer des actions en interaction avec le monde extérieur. Les outils actuellement disponibles sont :
PythonREPL
- un outil qui permet aux agents d'exécuter du code Python dans un REPL.IsolatedPythonREPL
- un outil qui permet aux agents d'exécuter du code Python dans un REPL, mais dans un conteneur Docker.BashTerminal
- un outil qui permet aux agents d'exécuter des commandes bash dans un terminal.GoogleSearch
- un outil qui permet aux agents d'effectuer des recherches sur Google.WebpageSummary
- un outil basé sur LLM qui permet aux agents d'obtenir un résumé d'une page Web.WolframAlpha
- un outil qui permet aux agents d'interroger l'API à réponse courte de WolframAlpha.KeyValueStore
- un outil pour stocker et récupérer des informations. L'agent peut utiliser cet outil pour réutiliser de longues informations par référence, supprimant ainsi la duplication et réduisant ainsi la taille du contexte.AskUser
- un outil d'interactivité qui permet à l'agent de demander des éclaircissements à un opérateur humain en cas de besoin.JSONAutoFixer
- un méta-outil activé par défaut. Lorsque les arguments d'un outil sont fournis sous une forme qui n'est pas un JSON valide, cet outil tente de corriger la charge utile à l'aide d'une chaîne LLM distincte.GenericAgentTool
- permet à un agent d'exécuter un autre agent, avec des outils prédéterminés, en lui fournissant dynamiquement sa tâche et ses entrées et en collectant sa réponse finale.Avertissement
Les outils
BashTerminal
etPythonREPL
classiques permettent à l'agent d'exécuter des commandes arbitraires sur votre machine, à utiliser à vos propres risques. Cela peut être une bonne idée d'utiliser la prise en charge intégrée des rappels de confirmation d'action (voir la méthodeWithActionConfirmation
sur le typeChainAgent
).
Les outils go-llm
prennent en charge la nouvelle interface d'appel de fonction OpenAI de manière transparente, pour les variantes de modèles dotées de cette fonctionnalité.
Un système de mémoire qui permet aux agents de stocker et de récupérer des informations. Les systèmes de mémoire actuellement disponibles sont :
BufferMemory
- qui fournit à chaque étape de l'agent un tampon fixe de messages récents de l'historique des conversations.SummarisedMemory
- qui fournit à chaque étape de l'agent un résumé de l'historique des conversations, alimenté par un LLM.Les agents sont le composant principal de la bibliothèque. Les agents peuvent effectuer des tâches complexes impliquant des interactions itératives avec le monde extérieur.
Une collection d'agents prêts à l'emploi qui peuvent être facilement intégrés à votre application.
Une collection d’outils d’évaluation pour les agents et les moteurs.
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 ])
}