包含: - 核心配置文件(AGENTS.md, SOUL.md, USER.md等) - 记忆系统(memory/文件夹) - 技能库(skills/文件夹) - 小说内容(novel/文件夹) - .gitignore配置
221 lines
9.2 KiB
Markdown
221 lines
9.2 KiB
Markdown
# CallBack 定义方法
|
||
|
||
## 方法说明
|
||
|
||
### 1、BeforeModelCallBack
|
||
type BeforeModelCallback func(ctx agent.CallbackContext, llmRequest *model.LLMRequest) (*model.LLMResponse, error)
|
||
|
||
BeforeModelCallback that is called before sending a request to the model.
|
||
If it returns non-nil LLMResponse or error, the actual model call is skipped
|
||
and the returned response/error is used.
|
||
|
||
### 2、AfterModelCallback
|
||
type AfterModelCallback func(ctx agent.CallbackContext, llmResponse *model.LLMResponse, llmResponseError error) (*model.LLMResponse, error)
|
||
|
||
AfterModelCallback that is called after receiving a response from the model.
|
||
If it returns non-nil LLMResponse or error, the actual model response/error
|
||
is replaced with the returned response/error.
|
||
|
||
### 3、BeforeToolCallback
|
||
type BeforeToolCallback func(ctx tool.Context, tool tool.Tool, args map[string]any) (map[string]any, error)
|
||
|
||
BeforeToolCallback is executed before a tool's Run method.
|
||
Callbacks are executed in the order they are provided.
|
||
If a callback returns a non-nil result or an error:
|
||
- execution of remaining callbacks stops
|
||
- the actual tool call is skipped
|
||
- the returned result is used as the tool result
|
||
|
||
To modify tool arguments and still run the tool,
|
||
update args in place and return (nil, nil).
|
||
|
||
### 4、AfterToolCallback
|
||
type AfterToolCallback func(ctx tool.Context, tool tool.Tool, args, result map[string]any, err error) (map[string]any, error)
|
||
AfterToolCallback is a function type executed after a tool's Run method has completed,
|
||
regardless of whether the tool returned a result or an error.
|
||
|
||
Callbacks are executed in the order they are provided.
|
||
If a callback returns a non-nil result or an error:
|
||
- execution of remaining callbacks stops
|
||
- the returned result and/or error is used as the final tool output
|
||
|
||
|
||
## callback方法示例
|
||
|
||
### 1、BeforeModelCallBack 代码示例
|
||
何时触发: 在LlmAgent流程中向 LLM 发送请求之前调用。
|
||
用途: 允许检查和修改发送给 LLM 的请求。用例包括添加动态指令、基于状态注入少量示例、修改模型配置、实现防护机制 (如亵渎过滤器) 或实现请求级缓存。
|
||
返回值效果: 如果回调返回 nil,LLM 继续其正常工作流程。如果回调返回 LlmResponse 对象,则跳过对 LLM 的调用。返回的 LlmResponse 直接使用,就像它来自模型一样。这对于实现防护栏或缓存非常强大。
|
||
|
||
```go
|
||
func onBeforeModel(ctx agent.CallbackContext, req *model.LLMRequest) (*model.LLMResponse, error) {
|
||
log.Printf("[Callback] BeforeModel triggered for agent %q.", ctx.AgentName())
|
||
|
||
// Modification Example: Add a prefix to the system instruction.
|
||
if req.Config.SystemInstruction != nil {
|
||
prefix := "[Modified by Callback] "
|
||
// This is a simplified example; production code might need deeper checks.
|
||
if len(req.Config.SystemInstruction.Parts) > 0 {
|
||
req.Config.SystemInstruction.Parts[0].Text = prefix + req.Config.SystemInstruction.Parts[0].Text
|
||
} else {
|
||
req.Config.SystemInstruction.Parts = append(req.Config.SystemInstruction.Parts, &genai.Part{Text: prefix})
|
||
}
|
||
log.Printf("[Callback] Modified system instruction.")
|
||
}
|
||
|
||
// Skip Example: Check for "BLOCK" in the user's prompt.
|
||
for _, content := range req.Contents {
|
||
for _, part := range content.Parts {
|
||
if strings.Contains(strings.ToUpper(part.Text), "BLOCK") {
|
||
log.Println("[Callback] 'BLOCK' keyword found. Skipping LLM call.")
|
||
return &model.LLMResponse{
|
||
Content: &genai.Content{
|
||
Parts: []*genai.Part{{Text: "LLM call was blocked by before_model_callback."}},
|
||
Role: "model",
|
||
},
|
||
}, nil
|
||
}
|
||
}
|
||
}
|
||
|
||
log.Println("[Callback] Proceeding with LLM call.")
|
||
return nil, nil
|
||
}
|
||
|
||
rootAgent, err := veagent.New(&veagent.Config{
|
||
Config: llmagent.Config{
|
||
Name: "...",
|
||
Description: "...",
|
||
Instruction: "...",
|
||
BeforeModelCallbacks:[]llmagent.BeforeModelCallback{
|
||
onBeforeModel,
|
||
},
|
||
},
|
||
})
|
||
```
|
||
|
||
### 2、AfterModelCallBack 代码示例
|
||
何时触发: 在从 LLM 接收到响应 (LlmResponse) 之后,在调用智能体进一步处理之前调用。
|
||
用途: 允许检查或修改原始 LLM 响应。用例包括:
|
||
记录模型输出,
|
||
重新格式化响应,
|
||
审查模型生成的敏感信息,
|
||
从 LLM 响应中解析结构化数据并将其存储在callback_context.state中
|
||
或处理特定错误代码。
|
||
|
||
```go
|
||
func onAfterModel(ctx agent.CallbackContext, resp *model.LLMResponse, respErr error) (*model.LLMResponse, error) {
|
||
log.Printf("[Callback] AfterModel triggered for agent %q.", ctx.AgentName())
|
||
if respErr != nil {
|
||
log.Printf("[Callback] Model returned an error: %v. Passing it through.", respErr)
|
||
return nil, respErr
|
||
}
|
||
if resp == nil || resp.Content == nil || len(resp.Content.Parts) == 0 {
|
||
log.Println("[Callback] Response is nil or has no parts, nothing to process.")
|
||
return nil, nil
|
||
}
|
||
// Check for function calls and pass them through without modification.
|
||
if resp.Content.Parts[0].FunctionCall != nil {
|
||
log.Println("[Callback] Response is a function call. No modification.")
|
||
return nil, nil
|
||
}
|
||
|
||
originalText := resp.Content.Parts[0].Text
|
||
|
||
// Use a case-insensitive regex with word boundaries to find "joke".
|
||
re := regexp.MustCompile(`(?i)\bjoke\b`)
|
||
if !re.MatchString(originalText) {
|
||
log.Println("[Callback] 'joke' not found. Passing original response through.")
|
||
return nil, nil
|
||
}
|
||
|
||
log.Println("[Callback] 'joke' found. Modifying response.")
|
||
// Use a replacer function to handle capitalization.
|
||
modifiedText := re.ReplaceAllStringFunc(originalText, func(s string) string {
|
||
if strings.ToUpper(s) == "JOKE" {
|
||
if s == "Joke" {
|
||
return "Funny story"
|
||
}
|
||
return "funny story"
|
||
}
|
||
return s // Should not be reached with this regex, but it's safe.
|
||
})
|
||
|
||
resp.Content.Parts[0].Text = modifiedText
|
||
return resp, nil
|
||
}
|
||
```
|
||
|
||
### 3、BeforeToolCallback 代码示例
|
||
|
||
何时触发: 在调用特定工具的run_async方法之前,在 LLM 为其生成函数调用之后调用。
|
||
|
||
用途: 允许检查和修改工具参数,在执行前执行授权检查,记录工具使用尝试,或实现工具级缓存。
|
||
|
||
返回值效果:
|
||
|
||
如果回调返回 nil,工具方法将使用(可能修改的)args 执行。
|
||
如果返回map,工具方法将被跳过。返回的字典直接用作工具调用的结果。这对于缓存或覆盖工具行为很有用。
|
||
|
||
```go
|
||
func onBeforeTool(ctx tool.Context, t tool.Tool, args map[string]any) (map[string]any, error) {
|
||
log.Printf("[Callback] BeforeTool triggered for tool %q in agent %q.", t.Name(), ctx.AgentName())
|
||
log.Printf("[Callback] Original args: %v", args)
|
||
|
||
if t.Name() == "getCapitalCity" {
|
||
if country, ok := args["country"].(string); ok {
|
||
if strings.ToLower(country) == "canada" {
|
||
log.Println("[Callback] Detected 'Canada'. Modifying args to 'France'.")
|
||
args["country"] = "France"
|
||
return args, nil // Proceed with modified args
|
||
} else if strings.ToUpper(country) == "BLOCK" {
|
||
log.Println("[Callback] Detected 'BLOCK'. Skipping tool execution.")
|
||
// Skip tool and return a custom result.
|
||
return map[string]any{"result": "Tool execution was blocked by before_tool_callback."}, nil
|
||
}
|
||
}
|
||
}
|
||
log.Println("[Callback] Proceeding with original or previously modified args.")
|
||
return nil, nil // Proceed with original args
|
||
}
|
||
```
|
||
|
||
### 4、AfterToolCallback 代码示例
|
||
何时触发: 在工具的执行方法成功完成后立即调用。
|
||
用途: 允许在将工具结果发送回 LLM(可能在摘要后) 之前对其进行检查和修改。适用于记录工具结果、后处理或格式化结果,或将结果的特定部分保存到会话状态。
|
||
|
||
返回值效果:
|
||
如果回调返回 nil,使用原始的 tool_response。
|
||
如果返回新map,它替换原始的 tool_response。这允许修改或过滤 LLM 看到的结果。
|
||
|
||
```go
|
||
func onAfterTool(ctx tool.Context, t tool.Tool, args map[string]any, result map[string]any, err error) (map[string]any, error) {
|
||
log.Printf("[Callback] AfterTool triggered for tool %q in agent %q.", t.Name(), ctx.AgentName())
|
||
log.Printf("[Callback] Original result: %v", result)
|
||
|
||
if err != nil {
|
||
log.Printf("[Callback] Tool run produced an error: %v. Passing through.", err)
|
||
return nil, err
|
||
}
|
||
|
||
if t.Name() == "getCapitalCity" {
|
||
if originalResult, ok := result["result"].(string); ok && originalResult == "Washington, D.C." {
|
||
log.Println("[Callback] Detected 'Washington, D.C.'. Modifying tool response.")
|
||
modifiedResult := make(map[string]any)
|
||
for k, v := range result {
|
||
modifiedResult[k] = v
|
||
}
|
||
modifiedResult["result"] = fmt.Sprintf("%s (Note: This is the capital of the USA).", originalResult)
|
||
modifiedResult["note_added_by_callback"] = true
|
||
return modifiedResult, nil
|
||
}
|
||
}
|
||
|
||
log.Println("[Callback] Passing original tool response through.")
|
||
return nil, nil
|
||
}
|
||
```
|
||
|
||
|
||
|