chore: initial scaffold with design docs
This commit is contained in:
commit
c21173a7f8
12 changed files with 757 additions and 0 deletions
19
.gitignore
vendored
Normal file
19
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
# Go
|
||||||
|
*.exe
|
||||||
|
*.test
|
||||||
|
*.out
|
||||||
|
*.prof
|
||||||
|
vendor/
|
||||||
|
coverage.out
|
||||||
|
coverage.html
|
||||||
|
|
||||||
|
# Editor / OS
|
||||||
|
.vscode/
|
||||||
|
.idea/
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
*~
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
# Local build cache
|
||||||
|
.cache/
|
||||||
21
LICENSE
Normal file
21
LICENSE
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2026 Victor Hugo Vargas Servín
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
137
README.md
Normal file
137
README.md
Normal file
|
|
@ -0,0 +1,137 @@
|
||||||
|
# go-llm-agent
|
||||||
|
|
||||||
|
> 🔑 **Librería core reutilizable** para construir agentes LLM en Go.
|
||||||
|
|
||||||
|
Esta librería es el corazón de varios proyectos de Victor Vargas:
|
||||||
|
- [`harness`](https://github.com/VictorVargas/harness) — AI agent harness para desarrollo de software (TUI)
|
||||||
|
- [`chat-bot`](https://github.com/VictorVargas/chat-bot) — Chatbot HTTP para portfolios y sitios web
|
||||||
|
|
||||||
|
Provee toda la lógica **genérica** de un agente LLM:
|
||||||
|
|
||||||
|
| Componente | Ubicación | Responsabilidad |
|
||||||
|
|---|---|---|
|
||||||
|
| **Agent loop** | `pkg/agent/` | Bucle iterativo con guardrails |
|
||||||
|
| **LLM clients** | `pkg/llm/` | Abstracción multi-provider (OpenAI, Anthropic, Ollama) |
|
||||||
|
| **RAG / memoria** | `pkg/rag/` | Memoria de corto y largo plazo con búsqueda semántica |
|
||||||
|
| **Persona system** | `pkg/persona/` | System prompts configurables + AGENTS.md discovery |
|
||||||
|
| **Tool registry** | `pkg/tools/` | JSON Schema + execution sandbox |
|
||||||
|
| **Config loading** | `pkg/config/` | Carga de YAML con precedencia jerárquica |
|
||||||
|
|
||||||
|
## 🎯 Filosofía
|
||||||
|
|
||||||
|
- **Reusable, no opinionated.** No fuerza un tipo de UI, deployment, ni use case.
|
||||||
|
- **Hexagonal.** Ports & adapters permiten sustituir cualquier pieza.
|
||||||
|
- **Streaming-first.** Usa `iter.Seq2` de Go 1.23+ para streaming sin boilerplate.
|
||||||
|
- **Seguridad por defecto.** Sandbox de paths con `os.Root` (Go 1.24+).
|
||||||
|
|
||||||
|
## 📦 Instalación
|
||||||
|
|
||||||
|
```bash
|
||||||
|
go get github.com/VictorVargas/go-llm-agent
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔧 Setup del proyecto (si vas a contribuir)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/VictorVargas/go-llm-agent.git
|
||||||
|
cd go-llm-agent
|
||||||
|
|
||||||
|
# El go.mod ya existe con module + go version
|
||||||
|
# Las dependencias se agregan automáticamente cuando escribes código:
|
||||||
|
|
||||||
|
# 1. Escribe tu código importando paquetes
|
||||||
|
# 2. Ejecuta:
|
||||||
|
go mod tidy # resuelve imports → actualiza go.mod + crea go.sum
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🚀 Uso básico
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"github.com/VictorVargas/go-llm-agent/pkg/agent"
|
||||||
|
"github.com/VictorVargas/go-llm-agent/pkg/llm"
|
||||||
|
"github.com/VictorVargas/go-llm-agent/pkg/persona"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// 1. Crear cliente LLM
|
||||||
|
llmClient, _ := llm.NewAnthropicClient(llm.AnthropicConfig{
|
||||||
|
APIKey: os.Getenv("ANTHROPIC_API_KEY"),
|
||||||
|
Model: "claude-sonnet-4.5",
|
||||||
|
})
|
||||||
|
|
||||||
|
// 2. Cargar persona
|
||||||
|
p := persona.Load("./persona.yaml")
|
||||||
|
|
||||||
|
// 3. Crear agent loop
|
||||||
|
loop := agent.New(agent.Config{
|
||||||
|
LLM: llmClient,
|
||||||
|
Persona: p,
|
||||||
|
MaxIters: 50,
|
||||||
|
Sandbox: agent.NewSandbox("./workspace"),
|
||||||
|
})
|
||||||
|
|
||||||
|
// 4. Ejecutar
|
||||||
|
resp, err := loop.Run(context.Background(), "Refactoriza auth.go")
|
||||||
|
if err != nil { panic(err) }
|
||||||
|
|
||||||
|
fmt.Println(resp.Content)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔌 Adapters incluidos
|
||||||
|
|
||||||
|
### LLM Providers (`pkg/llm/providers/`)
|
||||||
|
|
||||||
|
| Provider | Import | Modelos |
|
||||||
|
|---|---|---|
|
||||||
|
| OpenAI | `llm/providers/openai` | gpt-4o, gpt-4o-mini, gpt-4-turbo |
|
||||||
|
| Anthropic | `llm/providers/anthropic` | claude-sonnet-4.5, claude-haiku-4 |
|
||||||
|
| Ollama | `llm/providers/ollama` | llama3.1, qwen2.5, mistral, etc. |
|
||||||
|
| llama.cpp | `llm/providers/llamacpp` | Custom GGUF models |
|
||||||
|
|
||||||
|
### Vector DBs (`pkg/rag/backends/`)
|
||||||
|
|
||||||
|
| Backend | Estado |
|
||||||
|
|---|---|
|
||||||
|
| ChromaDB embedded | ✅ Estable |
|
||||||
|
| Qdrant embedded | 🚧 En desarrollo |
|
||||||
|
| SQLite + sqlite-vec | 📋 Planeado |
|
||||||
|
|
||||||
|
### Embeddings (`pkg/rag/embeddings/`)
|
||||||
|
|
||||||
|
- Ollama embeddings (nomic-embed-text, bge-m3, etc.)
|
||||||
|
- Local sentence-transformers via ONNX
|
||||||
|
|
||||||
|
## 🧪 Testing
|
||||||
|
|
||||||
|
```bash
|
||||||
|
go test ./...
|
||||||
|
go test -race ./...
|
||||||
|
go test -bench=. ./pkg/agent/
|
||||||
|
```
|
||||||
|
|
||||||
|
Incluye `MockLLMClient` para tests deterministas sin gastar API calls.
|
||||||
|
|
||||||
|
## 📐 Versiones
|
||||||
|
|
||||||
|
- **Go mínimo:** 1.26 (usa `os.Root`, `iter.Seq`, `unique.Handle`, container-aware GOMAXPROCS)
|
||||||
|
- **Política de versionado:** Semver estricto. API breaking changes solo en MAJOR.
|
||||||
|
|
||||||
|
## 📄 Licencia
|
||||||
|
|
||||||
|
MIT — ver [`LICENSE`](./LICENSE).
|
||||||
|
|
||||||
|
## 🔗 Proyectos que usan esta librería
|
||||||
|
|
||||||
|
- [`VictorVargas/harness`](https://github.com/VictorVargas/harness) — TUI agent para software dev
|
||||||
|
- [`VictorVargas/chat-bot`](https://github.com/VictorVargas/chat-bot) — HTTP chatbot
|
||||||
|
|
||||||
|
## 📚 Documentación adicional
|
||||||
|
|
||||||
|
- [Architecture overview](./docs/README.md)
|
||||||
|
- [Design decisions](./docs/architecture.md) (próximamente)
|
||||||
93
docs/README.md
Normal file
93
docs/README.md
Normal file
|
|
@ -0,0 +1,93 @@
|
||||||
|
# go-llm-agent — Documentación
|
||||||
|
|
||||||
|
Documentación técnica detallada de la librería.
|
||||||
|
|
||||||
|
## 📐 Arquitectura
|
||||||
|
|
||||||
|
```
|
||||||
|
┌────────────────────────────────────────────────────────────────┐
|
||||||
|
│ go-llm-agent (pkg/) │
|
||||||
|
│ │
|
||||||
|
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────────┐ │
|
||||||
|
│ │ agent │ │ persona │ │ tools │ │
|
||||||
|
│ │ │ │ │ │ │ │
|
||||||
|
│ │ Agent loop │◄─┤ Persona │ │ Tool registry │ │
|
||||||
|
│ │ con guard- │ │ + AGENTS.md │ │ + JSON Schema │ │
|
||||||
|
│ │ rails │ │ discovery │ │ + execution │ │
|
||||||
|
│ └──────┬───────┘ └──────────────┘ └────────┬─────────┘ │
|
||||||
|
│ │ │ │
|
||||||
|
│ ▼ ▼ │
|
||||||
|
│ ┌──────────────┐ ┌──────────────┐ │
|
||||||
|
│ │ llm │ │ rag │ │
|
||||||
|
│ │ │ │ │ │
|
||||||
|
│ │ LLMClient │ │ Memory + │ │
|
||||||
|
│ │ interface + │ │ Embeddings │ │
|
||||||
|
│ │ providers │ │ + VectorDB │ │
|
||||||
|
│ └──────────────┘ └──────────────┘ │
|
||||||
|
│ │
|
||||||
|
└────────────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📦 Paquetes
|
||||||
|
|
||||||
|
| Paquete | Responsabilidad | Docs |
|
||||||
|
|---|---|---|
|
||||||
|
| `pkg/agent` | Bucle iterativo, termination conditions, approval gates | [Ver](../pkg/agent/README.md) |
|
||||||
|
| `pkg/llm` | `LLMClient` interface, streaming, providers | [Ver](../pkg/llm/README.md) |
|
||||||
|
| `pkg/rag` | Memoria, embeddings, búsqueda semántica | [Ver](../pkg/rag/README.md) |
|
||||||
|
| `pkg/persona` | System prompts, AGENTS.md, few-shot examples | [Ver](../pkg/persona/README.md) |
|
||||||
|
| `pkg/tools` | Tool registry, JSON Schema, sandboxing | [Ver](../pkg/tools/README.md) |
|
||||||
|
| `pkg/config` | YAML loading, precedence, env override | [Ver](../pkg/config/README.md) |
|
||||||
|
|
||||||
|
## 🎯 Principios de diseño
|
||||||
|
|
||||||
|
### 1. Streaming-first
|
||||||
|
Usa `iter.Seq2[T, error]` de Go 1.23+ para streaming natural:
|
||||||
|
|
||||||
|
```go
|
||||||
|
for token, err := range llmClient.StreamTokens(ctx, req) {
|
||||||
|
if err != nil { return err }
|
||||||
|
fmt.Print(token)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Hexagonal puro
|
||||||
|
Cada paquete expone interfaces, las implementaciones concretas están separadas:
|
||||||
|
|
||||||
|
```go
|
||||||
|
// pkg/rag/rag.go (puerto)
|
||||||
|
type VectorDB interface {
|
||||||
|
Search(ctx context.Context, embedding []float32, topK int) ([]Document, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// pkg/rag/backends/chroma/chroma.go (adapter)
|
||||||
|
type ChromaDB struct { ... }
|
||||||
|
func (c *ChromaDB) Search(...) { ... }
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Seguridad por defecto
|
||||||
|
- `os.Root` para sandbox de filesystem (Go 1.24+)
|
||||||
|
- Approval gates antes de tools destructivos
|
||||||
|
- Bash sandbox con denylist + timeout
|
||||||
|
- Network egress control opcional
|
||||||
|
|
||||||
|
### 4. Zero magic
|
||||||
|
No hay reflection, no hay code generation, no hay DSLs. Todo es Go idiomático y explícito.
|
||||||
|
|
||||||
|
## 🔄 Versionado
|
||||||
|
|
||||||
|
- **Semver estricto** (`vMAJOR.MINOR.PATCH`)
|
||||||
|
- **MAJOR**: breaking changes en `pkg/` (interfaces, signatures, tipos públicos)
|
||||||
|
- **MINOR**: nuevas features, nuevos paquetes, nuevos adapters
|
||||||
|
- **PATCH**: bugfixes
|
||||||
|
|
||||||
|
Los adapters privados (`pkg/llm/providers/openai/`) pueden cambiar sin bump de MAJOR si la interfaz `LLMClient` no cambia.
|
||||||
|
|
||||||
|
## 🚧 Estado actual
|
||||||
|
|
||||||
|
⚠️ **Esta librería está en diseño activo.** El código todavía no está implementado. La especificación completa está en los design docs de los proyectos que la consumen:
|
||||||
|
|
||||||
|
- [`VictorVargas/harness/docs/architecture.md`](https://github.com/VictorVargas/harness/blob/main/docs/architecture.md) — Define los requirements
|
||||||
|
- [`VictorVargas/harness/docs/phase2.md`](https://github.com/VictorVargas/harness/blob/main/docs/phase2.md) — Features avanzadas
|
||||||
|
|
||||||
|
Una vez que `harness/` esté implementado, esta librería se extraerá como código real.
|
||||||
29
examples/README.md
Normal file
29
examples/README.md
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
# Examples
|
||||||
|
|
||||||
|
> Ejemplos de uso de `go-llm-agent` en distintos contextos.
|
||||||
|
|
||||||
|
## 📁 Contenido planeado
|
||||||
|
|
||||||
|
| Ejemplo | Descripción | Estado |
|
||||||
|
|---|---|---|
|
||||||
|
| `simple_chat/` | Chat básico sin tools | 📋 Pendiente |
|
||||||
|
| `chat_with_tools/` | Chat con tools custom | 📋 Pendiente |
|
||||||
|
| `rag_qa/` | Q&A sobre documentos | 📋 Pendiente |
|
||||||
|
| `multi_agent/` | Orquestación de sub-agents | 📋 Pendiente |
|
||||||
|
| `streaming_ui/` | Integración con TUI | 📋 Pendiente |
|
||||||
|
|
||||||
|
## 🎯 Cómo correr los ejemplos (cuando existan)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd examples/simple_chat
|
||||||
|
go mod tidy
|
||||||
|
export ANTHROPIC_API_KEY=sk-ant-...
|
||||||
|
go run main.go
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📝 Contribuir
|
||||||
|
|
||||||
|
Cada ejemplo debe ser:
|
||||||
|
- ✅ **Standalone**: `go run main.go` y funciona
|
||||||
|
- ✅ **Mínimo**: <100 líneas si es posible
|
||||||
|
- ✅ **Documentado**: README con qué demuestra y cómo extenderlo
|
||||||
3
go.mod
Normal file
3
go.mod
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
module github.com/VictorVargas/go-llm-agent
|
||||||
|
|
||||||
|
go 1.26
|
||||||
57
pkg/agent/README.md
Normal file
57
pkg/agent/README.md
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
# pkg/agent
|
||||||
|
|
||||||
|
> El bucle principal que ejecuta un agente LLM con guardrails.
|
||||||
|
|
||||||
|
## Responsabilidad
|
||||||
|
|
||||||
|
Coordinar el ciclo iterativo entre el LLM y la ejecución de tools:
|
||||||
|
|
||||||
|
```
|
||||||
|
while iteration < MaxIterations:
|
||||||
|
response = llm.Generate(messages, tools)
|
||||||
|
if no tool calls: return response
|
||||||
|
for tool_call in response.ToolCalls:
|
||||||
|
if needs_approval: ask_user()
|
||||||
|
result = execute(tool_call)
|
||||||
|
append tool result to messages
|
||||||
|
```
|
||||||
|
|
||||||
|
## API pública
|
||||||
|
|
||||||
|
```go
|
||||||
|
type Loop interface {
|
||||||
|
Run(ctx context.Context, input string) (Response, error)
|
||||||
|
RunStream(ctx context.Context, input string) iter.Seq2[Chunk, error]
|
||||||
|
}
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
LLM llm.LLMClient
|
||||||
|
Persona persona.Persona
|
||||||
|
Tools tools.Registry
|
||||||
|
Sandbox Sandbox
|
||||||
|
MaxIters int
|
||||||
|
Approver Approver // nil = auto-approve all
|
||||||
|
OnIteration func(Iteration) // observability hook
|
||||||
|
}
|
||||||
|
|
||||||
|
type Response struct {
|
||||||
|
Content string
|
||||||
|
ToolCalls []tools.Call
|
||||||
|
Iterations int
|
||||||
|
Duration time.Duration
|
||||||
|
TokenUsage llm.TokenUsage
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Garantías
|
||||||
|
|
||||||
|
- **Termination**: Siempre termina (max iterations, error, o respuesta final)
|
||||||
|
- **Idempotencia**: Re-ejecutar con el mismo input produce el mismo output (dado el mismo LLM)
|
||||||
|
- **Observabilidad**: Cada iteración emite un span OpenTelemetry
|
||||||
|
- **Approval**: Tool destructivos (`Ask` permission) requieren confirmación
|
||||||
|
|
||||||
|
## Ver también
|
||||||
|
|
||||||
|
- [pkg/tools](../tools/README.md) — Tool execution
|
||||||
|
- [pkg/llm](../llm/README.md) — LLMClient interface
|
||||||
|
- [pkg/persona](../persona/README.md) — Persona assembly
|
||||||
81
pkg/config/README.md
Normal file
81
pkg/config/README.md
Normal file
|
|
@ -0,0 +1,81 @@
|
||||||
|
# pkg/config
|
||||||
|
|
||||||
|
> Carga de configuración YAML con precedencia jerárquica.
|
||||||
|
|
||||||
|
## Responsabilidad
|
||||||
|
|
||||||
|
Resolver la configuración final del agente combinando múltiples fuentes con orden de precedencia:
|
||||||
|
|
||||||
|
1. **Flags CLI** (highest)
|
||||||
|
2. **Environment variables**
|
||||||
|
3. **Project config** (`./.rony.yaml`)
|
||||||
|
4. **Global config** (`~/.config/rony/config.yaml`)
|
||||||
|
5. **Defaults embebidos** (lowest)
|
||||||
|
|
||||||
|
## API pública
|
||||||
|
|
||||||
|
```go
|
||||||
|
type Config struct {
|
||||||
|
Model string
|
||||||
|
Persona string
|
||||||
|
Provider ProviderConfig
|
||||||
|
Tools ToolPolicy
|
||||||
|
Logging LoggingConfig
|
||||||
|
Sandbox SandboxConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
type Loader interface {
|
||||||
|
Load(ctx context.Context, workdir string) (Config, error)
|
||||||
|
LoadFromBytes(data []byte, source string) (Config, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type ProviderConfig struct {
|
||||||
|
Type string // "openai" | "anthropic" | "ollama" | "llamacpp"
|
||||||
|
Model string
|
||||||
|
APIKey string // resuelto de env si es referencia
|
||||||
|
Endpoint string
|
||||||
|
}
|
||||||
|
|
||||||
|
type ToolPolicy map[string]tools.Permission
|
||||||
|
```
|
||||||
|
|
||||||
|
## Formato YAML
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# ~/.config/rony/config.yaml
|
||||||
|
model: claude-sonnet-4.5
|
||||||
|
persona: pragmatista
|
||||||
|
provider:
|
||||||
|
type: anthropic
|
||||||
|
api_key_env: ANTHROPIC_API_KEY
|
||||||
|
tools:
|
||||||
|
bash: ask
|
||||||
|
read: allow
|
||||||
|
write: ask
|
||||||
|
logging:
|
||||||
|
level: info
|
||||||
|
format: json
|
||||||
|
sandbox:
|
||||||
|
workspace: .
|
||||||
|
timeout_ms: 30000
|
||||||
|
```
|
||||||
|
|
||||||
|
## Override por env
|
||||||
|
|
||||||
|
```bash
|
||||||
|
RONY_MODEL=gpt-4o rony chat # override model
|
||||||
|
RONY_LOG_LEVEL=debug rony chat # override log level
|
||||||
|
```
|
||||||
|
|
||||||
|
## Precedencia
|
||||||
|
|
||||||
|
El loader resuelve en este orden (mayor prioridad primero):
|
||||||
|
|
||||||
|
```
|
||||||
|
flag > RONY_* env > ./.rony.yaml > ~/.config/rony/config.yaml > defaults
|
||||||
|
```
|
||||||
|
|
||||||
|
## Ver también
|
||||||
|
|
||||||
|
- [pkg/agent](../agent/README.md) — Usa Config
|
||||||
|
- [pkg/llm](../llm/README.md) — ProviderConfig se mapea a LLMClient
|
||||||
91
pkg/llm/README.md
Normal file
91
pkg/llm/README.md
Normal file
|
|
@ -0,0 +1,91 @@
|
||||||
|
# pkg/llm
|
||||||
|
|
||||||
|
> Abstracción multi-provider para modelos de lenguaje.
|
||||||
|
|
||||||
|
## Responsabilidad
|
||||||
|
|
||||||
|
Definir una interfaz común (`LLMClient`) y adapters para los principales providers.
|
||||||
|
|
||||||
|
## API pública
|
||||||
|
|
||||||
|
```go
|
||||||
|
type LLMClient interface {
|
||||||
|
Generate(ctx context.Context, req CompletionRequest) (CompletionResponse, error)
|
||||||
|
Stream(ctx context.Context, req CompletionRequest) iter.Seq2[StreamChunk, error]
|
||||||
|
Name() string
|
||||||
|
Capabilities() ProviderCapabilities
|
||||||
|
}
|
||||||
|
|
||||||
|
type CompletionRequest struct {
|
||||||
|
Messages []Message
|
||||||
|
Tools []tools.Tool
|
||||||
|
ToolChoice ToolChoice
|
||||||
|
Model string
|
||||||
|
Temperature *float32
|
||||||
|
MaxTokens *int
|
||||||
|
}
|
||||||
|
|
||||||
|
type CompletionResponse struct {
|
||||||
|
Content string
|
||||||
|
ToolCalls []tools.Call
|
||||||
|
Usage TokenUsage
|
||||||
|
StopReason string
|
||||||
|
}
|
||||||
|
|
||||||
|
type ProviderCapabilities struct {
|
||||||
|
SupportsTools bool
|
||||||
|
SupportsVision bool
|
||||||
|
MaxContextWindow int
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Providers incluidos
|
||||||
|
|
||||||
|
| Provider | Paquete | Soporte tools |
|
||||||
|
|---|---|---|
|
||||||
|
| OpenAI | `providers/openai` | ✅ |
|
||||||
|
| Anthropic | `providers/anthropic` | ✅ |
|
||||||
|
| Ollama | `providers/ollama` | ✅ (modelos que lo soporten) |
|
||||||
|
| llama.cpp | `providers/llamacpp` | ✅ (con grammar) |
|
||||||
|
|
||||||
|
## Uso
|
||||||
|
|
||||||
|
```go
|
||||||
|
import "github.com/VictorVargas/go-llm-agent/pkg/llm/providers/anthropic"
|
||||||
|
|
||||||
|
client, err := anthropic.New(anthropic.Config{
|
||||||
|
APIKey: os.Getenv("ANTHROPIC_API_KEY"),
|
||||||
|
Model: "claude-sonnet-4.5",
|
||||||
|
})
|
||||||
|
|
||||||
|
resp, err := client.Generate(ctx, llm.CompletionRequest{
|
||||||
|
Messages: []llm.Message{
|
||||||
|
{Role: llm.RoleUser, Content: "Hola"},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
## Streaming
|
||||||
|
|
||||||
|
```go
|
||||||
|
for chunk, err := range client.Stream(ctx, req) {
|
||||||
|
if err != nil { return err }
|
||||||
|
fmt.Print(chunk.Delta)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Mock para tests
|
||||||
|
|
||||||
|
```go
|
||||||
|
import "github.com/VictorVargas/go-llm-agent/pkg/llm/mock"
|
||||||
|
|
||||||
|
mockClient := mock.New(mock.Responses{
|
||||||
|
{Match: "hola", Response: "¡Hola! ¿Cómo estás?"},
|
||||||
|
{Match: "*", Response: "default"},
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
## Ver también
|
||||||
|
|
||||||
|
- [pkg/agent](../agent/README.md) — Usa `LLMClient`
|
||||||
|
- [pkg/tools](../tools/README.md) — Las `Tool` definitions
|
||||||
71
pkg/persona/README.md
Normal file
71
pkg/persona/README.md
Normal file
|
|
@ -0,0 +1,71 @@
|
||||||
|
# pkg/persona
|
||||||
|
|
||||||
|
> Sistema de personalidades configurables para agentes LLM.
|
||||||
|
|
||||||
|
## Responsabilidad
|
||||||
|
|
||||||
|
Ensamblar el system prompt final del agente combinando:
|
||||||
|
|
||||||
|
1. **Base prompt** (hardcoded en la librería)
|
||||||
|
2. **Persona YAML** (configurable por proyecto)
|
||||||
|
3. **AGENTS.md** (instrucciones del proyecto, descubierto por búsqueda en árbol de directorios)
|
||||||
|
4. **Working memory context** (resúmenes si hay compaction)
|
||||||
|
|
||||||
|
## API pública
|
||||||
|
|
||||||
|
```go
|
||||||
|
type Persona struct {
|
||||||
|
ID string
|
||||||
|
Name string
|
||||||
|
Tone string
|
||||||
|
Style string
|
||||||
|
Language string
|
||||||
|
Constraints []string
|
||||||
|
FewShot []llm.Message
|
||||||
|
}
|
||||||
|
|
||||||
|
type Loader interface {
|
||||||
|
Load(ctx context.Context, configPath string) (Persona, error)
|
||||||
|
Discover(ctx context.Context, workdir string) (Persona, error) // incluye AGENTS.md
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Formato YAML
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
id: pragmatista
|
||||||
|
name: Pragmatista
|
||||||
|
tone: "Directo y profesional"
|
||||||
|
style: "Enfoque Go idiomatic"
|
||||||
|
language: "Español, con términos técnicos en inglés"
|
||||||
|
constraints:
|
||||||
|
- "No usar interface{} en código nuevo"
|
||||||
|
- "Siempre wrapped errors con %w"
|
||||||
|
few_shot:
|
||||||
|
- role: user
|
||||||
|
content: "Refactoriza este código"
|
||||||
|
- role: assistant
|
||||||
|
content: "Listo. Optimizado. ¿Aplico?"
|
||||||
|
```
|
||||||
|
|
||||||
|
## AGENTS.md discovery
|
||||||
|
|
||||||
|
El loader busca `./AGENTS.md`, sube al directorio padre, etc., concatenando todos los encontrados hasta llegar a `~` o `/`. También incluye `~/.config/rony/AGENTS.md` como default global.
|
||||||
|
|
||||||
|
```
|
||||||
|
/home/user/proyecto/AGENTS.md ← incluye
|
||||||
|
/home/user/AGENTS.md ← incluye
|
||||||
|
/home/AGENTS.md ← incluye
|
||||||
|
~/.config/rony/AGENTS.md ← incluye
|
||||||
|
```
|
||||||
|
|
||||||
|
## Uso
|
||||||
|
|
||||||
|
```go
|
||||||
|
p, err := persona.Discover(ctx, "/home/user/mi-proyecto")
|
||||||
|
// p.Content incluye todo lo anterior concatenado
|
||||||
|
```
|
||||||
|
|
||||||
|
## Ver también
|
||||||
|
|
||||||
|
- [pkg/agent](../agent/README.md) — Usa la persona en el system prompt
|
||||||
82
pkg/rag/README.md
Normal file
82
pkg/rag/README.md
Normal file
|
|
@ -0,0 +1,82 @@
|
||||||
|
# pkg/rag
|
||||||
|
|
||||||
|
> Retrieval-Augmented Generation: memoria, embeddings, y búsqueda semántica.
|
||||||
|
|
||||||
|
## Responsabilidad
|
||||||
|
|
||||||
|
Proveer memoria persistente y búsqueda semántica sobre el contenido del agente.
|
||||||
|
|
||||||
|
## Componentes
|
||||||
|
|
||||||
|
| Tipo | Qué guarda | Persistencia |
|
||||||
|
|---|---|---|
|
||||||
|
| **Working** | Mensajes de la sesión actual | RAM |
|
||||||
|
| **Episodic** | Eventos pasados (qué hice el día X) | Vector DB |
|
||||||
|
| **Semantic** | Conocimiento consolidado | Vector DB (curado) |
|
||||||
|
| **Procedural** | Patrones de uso (workflows) | Vector DB (auto-aprendido) |
|
||||||
|
|
||||||
|
## API pública
|
||||||
|
|
||||||
|
```go
|
||||||
|
type Memory interface {
|
||||||
|
Add(ctx context.Context, fragment Fragment) error
|
||||||
|
Search(ctx context.Context, query string, topK int) ([]Fragment, error)
|
||||||
|
Forget(ctx context.Context, id string) error
|
||||||
|
}
|
||||||
|
|
||||||
|
type Fragment struct {
|
||||||
|
ID string
|
||||||
|
Content string
|
||||||
|
Vector []float32
|
||||||
|
Metadata map[string]string
|
||||||
|
Timestamp time.Time
|
||||||
|
ProjectID string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Embedder interface {
|
||||||
|
Embed(ctx context.Context, text string) ([]float32, error)
|
||||||
|
Dimensions() int
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Backends
|
||||||
|
|
||||||
|
| Backend | Cuándo usar |
|
||||||
|
|---|---|
|
||||||
|
| ChromaDB embedded | Default. Simple, suficiente para <100k docs |
|
||||||
|
| Qdrant embedded | Si necesitas >100k docs o queries muy rápidas |
|
||||||
|
| SQLite + sqlite-vec | Si quieres zero-dependency (sin CGO con `modernc.org/sqlite`) |
|
||||||
|
|
||||||
|
## Embeddings
|
||||||
|
|
||||||
|
| Provider | Modelo | Dimensiones |
|
||||||
|
|---|---|---|
|
||||||
|
| Ollama | `nomic-embed-text` | 768 |
|
||||||
|
| Ollama | `bge-m3` | 1024 |
|
||||||
|
| Local ONNX | `all-MiniLM-L6-v2` | 384 |
|
||||||
|
|
||||||
|
## Uso
|
||||||
|
|
||||||
|
```go
|
||||||
|
import "github.com/VictorVargas/go-llm-agent/pkg/rag"
|
||||||
|
import "github.com/VictorVargas/go-llm-agent/pkg/rag/backends/chroma"
|
||||||
|
|
||||||
|
backend, _ := chroma.New(chroma.Config{
|
||||||
|
Path: "~/.local/share/rony/chroma",
|
||||||
|
})
|
||||||
|
|
||||||
|
memory := rag.New(rag.Config{
|
||||||
|
Backend: backend,
|
||||||
|
Embedder: ollamaEmbedder,
|
||||||
|
})
|
||||||
|
|
||||||
|
err := memory.Add(ctx, rag.Fragment{
|
||||||
|
Content: "Refactoricé auth.go usando hexagonal",
|
||||||
|
ProjectID: "rony",
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
## Ver también
|
||||||
|
|
||||||
|
- [pkg/agent](../agent/README.md) — Inyecta memoria al loop
|
||||||
|
- [pkg/llm](../llm/README.md) — Para summarization en compaction
|
||||||
73
pkg/tools/README.md
Normal file
73
pkg/tools/README.md
Normal file
|
|
@ -0,0 +1,73 @@
|
||||||
|
# pkg/tools
|
||||||
|
|
||||||
|
> Sistema de tools (function calling) con JSON Schema, sandbox, y permisos.
|
||||||
|
|
||||||
|
## Responsabilidad
|
||||||
|
|
||||||
|
Permitir que el LLM invoque funciones definidas en Go, con validación de schema y sandboxing.
|
||||||
|
|
||||||
|
## API pública
|
||||||
|
|
||||||
|
```go
|
||||||
|
type Tool struct {
|
||||||
|
Name string
|
||||||
|
Description string
|
||||||
|
InputSchema json.RawMessage // JSON Schema draft-07+
|
||||||
|
Handler Handler // func(ctx, args json.RawMessage) (Result, error)
|
||||||
|
Permission Permission // Allow | Ask | Deny
|
||||||
|
Examples []Example // few-shot para el LLM
|
||||||
|
}
|
||||||
|
|
||||||
|
type Registry interface {
|
||||||
|
Register(tool Tool) error
|
||||||
|
Get(name string) (Tool, bool)
|
||||||
|
List() []Tool
|
||||||
|
Filter(policy Policy) []Tool
|
||||||
|
}
|
||||||
|
|
||||||
|
type Call struct {
|
||||||
|
ID string
|
||||||
|
Name string
|
||||||
|
Arguments json.RawMessage
|
||||||
|
Thought string // opcional: chain-of-thought del LLM
|
||||||
|
}
|
||||||
|
|
||||||
|
type Result struct {
|
||||||
|
Content string
|
||||||
|
IsError bool
|
||||||
|
Metadata map[string]string
|
||||||
|
Artifacts []Artifact
|
||||||
|
}
|
||||||
|
|
||||||
|
type Permission int
|
||||||
|
|
||||||
|
const (
|
||||||
|
Allow Permission = iota
|
||||||
|
Ask
|
||||||
|
Deny
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Sandbox integrado
|
||||||
|
|
||||||
|
`pkg/tools` usa `os.Root` (Go 1.24+) para sandbox de filesystem:
|
||||||
|
|
||||||
|
```go
|
||||||
|
sandbox := tools.NewSandbox("./workspace")
|
||||||
|
sandbox.Register(myReadTool) // solo puede leer dentro del workspace
|
||||||
|
```
|
||||||
|
|
||||||
|
Ver [pkg/tools/sandbox/](sandbox/) para detalles.
|
||||||
|
|
||||||
|
## Tools genéricos incluidos
|
||||||
|
|
||||||
|
- `http_fetch` — GET a URL con HTML→markdown
|
||||||
|
- `json_parse` — Parse JSON arbitrario
|
||||||
|
- `datetime_now` — Current timestamp
|
||||||
|
|
||||||
|
Las tools específicas de cada producto (ej. `read_file`, `bash` para software dev) las define cada consumidor en su propio `internal/tools/`.
|
||||||
|
|
||||||
|
## Ver también
|
||||||
|
|
||||||
|
- [pkg/agent](../agent/README.md) — Ejecuta tool calls
|
||||||
|
- [pkg/llm](../llm/README.md) — Las tools se envían al LLM
|
||||||
Loading…
Reference in a new issue