go llm
1.0.0
大規模言語モデル (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
- エージェントが Web ページの概要を取得できるようにする 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 ])
}