2026-04-20 15:16:51 +08:00
|
|
|
package llm
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"context"
|
|
|
|
|
"fmt"
|
|
|
|
|
"log"
|
|
|
|
|
|
|
|
|
|
"github.com/tmc/langchaingo/llms"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type Agent struct {
|
2026-04-20 15:34:40 +08:00
|
|
|
client *Client
|
|
|
|
|
executor *ToolExecutor
|
2026-04-20 15:16:51 +08:00
|
|
|
}
|
|
|
|
|
|
2026-04-20 15:34:40 +08:00
|
|
|
func NewAgent(client *Client, executor *ToolExecutor) *Agent {
|
2026-04-20 15:16:51 +08:00
|
|
|
return &Agent{
|
2026-04-20 15:34:40 +08:00
|
|
|
client: client,
|
|
|
|
|
executor: executor,
|
2026-04-20 15:16:51 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (a *Agent) ChatWithTools(ctx context.Context, systemPrompt string, messages []llms.MessageContent) (string, error) {
|
2026-04-20 15:34:40 +08:00
|
|
|
tools := GetKnowledgeGraphTools()
|
2026-04-20 15:16:51 +08:00
|
|
|
|
2026-04-20 15:34:40 +08:00
|
|
|
builder := NewMessageBuilder().
|
|
|
|
|
WithSystemPrompt(systemPrompt).
|
|
|
|
|
WithMessages(messages)
|
2026-04-20 15:16:51 +08:00
|
|
|
|
|
|
|
|
maxIterations := 10
|
|
|
|
|
|
|
|
|
|
for i := 0; i < maxIterations; i++ {
|
2026-04-20 15:34:40 +08:00
|
|
|
resp, err := a.client.Generate(ctx, builder.Build(), llms.WithTools(tools))
|
2026-04-20 15:16:51 +08:00
|
|
|
if err != nil {
|
|
|
|
|
log.Printf("[ERROR] Agent GenerateContent failed: %v", err)
|
|
|
|
|
return "", fmt.Errorf("agent generate content error: %w", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if resp == nil || len(resp.Choices) == 0 {
|
|
|
|
|
log.Printf("[WARN] Agent response is empty or has no choices")
|
|
|
|
|
return "", fmt.Errorf("no content choices returned")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
choice := resp.Choices[0]
|
|
|
|
|
|
|
|
|
|
if len(choice.ToolCalls) == 0 {
|
|
|
|
|
log.Printf("[INFO] Agent chat completed successfully, choice length: %d", len(choice.Content))
|
|
|
|
|
return choice.Content, nil
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-20 15:34:40 +08:00
|
|
|
builder.AppendAIMessage(choice.Content, choice.ToolCalls)
|
2026-04-20 15:16:51 +08:00
|
|
|
|
|
|
|
|
for _, tc := range choice.ToolCalls {
|
|
|
|
|
log.Printf("[INFO] Executing tool call: %s, Args: %s", tc.FunctionCall.Name, tc.FunctionCall.Arguments)
|
|
|
|
|
|
2026-04-20 15:34:40 +08:00
|
|
|
toolResult, err := a.executor.Execute(tc)
|
2026-04-20 15:16:51 +08:00
|
|
|
if err != nil {
|
|
|
|
|
log.Printf("[WARN] Tool execution failed: %v", err)
|
|
|
|
|
toolResult = fmt.Sprintf(`{"error": "%s"}`, err.Error())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
log.Printf("[INFO] Tool call %s completed, result length: %d", tc.FunctionCall.Name, len(toolResult))
|
|
|
|
|
|
2026-04-20 15:34:40 +08:00
|
|
|
builder.AppendToolResult(tc.ID, tc.FunctionCall.Name, toolResult)
|
2026-04-20 15:16:51 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return "", fmt.Errorf("agent reached maximum tool call iterations (%d)", maxIterations)
|
2026-04-20 15:34:40 +08:00
|
|
|
}
|