LLM(대형 언어 모델)의 강력한 기능을 Go 애플리케이션에 통합하세요.
이 프로젝트는 에이전트의 비즈니스 로직에 집중할 수 있도록 많은 배관(구조화된 데이터에 대한 자유 텍스트, 상황별 메모리, 도구 래핑, 재시도 논리 등)을 추상화하는 것을 목표로 합니다.
그래프 LR
하위 그래프 입력
A[구조화된 입력] --> B[컴파일된 작업]
끝
하위 그래프 LLM 기반 에이전트
C[작업 템플릿] --> B[컴파일된 작업]
B --> D((대리인))
D --"추론"--> D
D --"작업"--> E[환경]
E --"관찰"--> D
D --"답변"--> G[출력 유효성 검사기]
G --> D
끝
하위 그래프 출력
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 엔진에 대한 커넥터입니다. 현재 OpenAI의 GPT 채팅 완료 API만 지원됩니다.
에이전트에게 외부 세계와 상호 작용하는 작업을 수행할 수 있는 기능을 제공할 수 있는 도구입니다. 현재 사용 가능한 도구는 다음과 같습니다.
PythonREPL
- 에이전트가 REPL에서 Python 코드를 실행할 수 있게 해주는 도구입니다.IsolatedPythonREPL
- 에이전트가 REPL이 아닌 Docker 컨테이너에서 Python 코드를 실행할 수 있게 해주는 도구입니다.BashTerminal
- 에이전트가 터미널에서 bash 명령을 실행할 수 있게 해주는 도구입니다.GoogleSearch
- 상담원이 Google을 검색할 수 있는 도구입니다.WebpageSummary
- 상담원이 웹페이지 요약을 얻을 수 있는 LLM 기반 도구입니다.WolframAlpha
- 에이전트가 WolframAlpha의 단답형 API를 쿼리할 수 있게 해주는 도구입니다.KeyValueStore
- 정보를 저장하고 검색하는 도구입니다. 에이전트는 이 도구를 사용하여 참조를 통해 긴 정보를 재사용하고 중복을 제거하여 컨텍스트 크기를 줄일 수 있습니다.AskUser
- 에이전트가 필요할 때 인간 운영자에게 설명을 요청할 수 있는 대화형 도구입니다.JSONAutoFixer
- 기본적으로 활성화되는 메타 도구입니다. 도구에 대한 인수가 유효한 JSON이 아닌 형식으로 제공되면 이 도구는 별도의 LLM 체인을 사용하여 페이로드를 수정하려고 시도합니다.GenericAgentTool
- 에이전트가 미리 결정된 도구를 사용하여 다른 에이전트를 실행하고 해당 작업과 입력을 동적으로 제공하고 최종 답변을 수집할 수 있습니다.경고
BashTerminal
및 일반PythonREPL
도구를 사용하면 에이전트가 컴퓨터에서 임의 명령을 실행할 수 있으며 사용에 따른 책임은 사용자에게 있습니다. 작업 확인 콜백에 대한 기본 지원을 사용하는 것이 좋습니다(ChainAgent
유형의WithActionConfirmation
메서드 참조).
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 ])
}