Integre el poder de los modelos de lenguaje grandes (LLM) en su aplicación Go.
Este proyecto tiene como objetivo abstraer gran parte de la plomería (texto libre a datos estructurados, memoria contextual, ajuste de herramientas, lógica de reintento, etc.) para que pueda concentrarse en la lógica de negocios de su agente.
gráfico LR
Entrada de subgrafo
A[Entrada estructurada] --> B[Tarea compilada]
fin
subgraph Agente basado en LLM
C[Plantilla de tarea] --> B[Tarea compilada]
B --> D((Agente))
D --"Razonamiento"--> D
D --"Acción"--> E[Entorno]
E --"Observación"--> D
D --"Respuesta"--> G[Validadores de salida]
G --> D
fin
Salida del subgrafo
G --"Respuesta"--> F[Salida estructurada]
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." ,
})
...
}
Nota
Dato curioso: el archivo
tools/bash_test.go
fue escrito por este mismo agente y ayudó a encontrar un error.
Conectores para motores LLM. Actualmente, solo se admite la API de finalización de chat GPT de OpenAI.
Herramientas que pueden proporcionar a los agentes la capacidad de realizar acciones interactuando con el mundo exterior. Las herramientas disponibles actualmente son:
PythonREPL
: una herramienta que permite a los agentes ejecutar código Python en un REPL.IsolatedPythonREPL
: una herramienta que permite a los agentes ejecutar código Python en un REPL, pero en un contenedor Docker.BashTerminal
: una herramienta que permite a los agentes ejecutar comandos bash en una terminal.GoogleSearch
: una herramienta que permite a los agentes realizar búsquedas en Google.WebpageSummary
: una herramienta basada en LLM que permite a los agentes obtener un resumen de una página web.WolframAlpha
: una herramienta que permite a los agentes consultar la API de respuesta corta de WolframAlpha.KeyValueStore
: una herramienta para almacenar y recuperar información. El agente puede utilizar esta herramienta para reutilizar piezas largas de información por referencia, eliminando la duplicación y, por tanto, reduciendo el tamaño del contexto.AskUser
: una herramienta de interactividad que permite al agente pedirle aclaraciones a un operador humano cuando sea necesario.JSONAutoFixer
: una metaherramienta que está habilitada de forma predeterminada. Cuando los argumentos de cualquier herramienta se proporcionan en un formato que no es JSON válido, esta herramienta intenta corregir la carga útil utilizando una cadena LLM separada.GenericAgentTool
: permite que un agente ejecute otro agente, con herramientas predeterminadas, proporcionándole dinámicamente su tarea e información y recopilando su respuesta final.Advertencia
BashTerminal
y las herramientas regularesPythonREPL
permiten que el agente ejecute comandos arbitrarios en su máquina; utilícelos bajo su propio riesgo. Puede ser una buena idea utilizar el soporte integrado para devoluciones de llamadas de confirmación de acciones (consulte el métodoWithActionConfirmation
en el tipoChainAgent
).
Las herramientas go-llm
admiten la nueva interfaz de llamada de función OpenAI de forma transparente, para las variantes de modelo que tienen esta característica.
Un sistema de memoria que permite a los agentes almacenar y recuperar información. Los sistemas de memoria disponibles actualmente son:
BufferMemory
: proporciona a cada paso del agente un búfer fijo de mensajes recientes del historial de conversaciones.SummarisedMemory
: proporciona a cada paso del agente un resumen del historial de conversaciones, impulsado por un LLM.Los agentes son el componente principal de la biblioteca. Los agentes pueden realizar tareas complejas que implican interacciones iterativas con el mundo exterior.
Una colección de agentes listos para usar que se pueden integrar fácilmente con su aplicación.
Una colección de herramientas de evaluación para agentes y motores.
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 ])
}