From f67126e8c30e8ed6817db722f11988f8be670136 Mon Sep 17 00:00:00 2001 From: juanatsap Date: Wed, 8 Apr 2026 00:30:01 +0100 Subject: [PATCH] docs: add AI Chat Agent documentation and update README - doc/28-AI-CHAT-AGENT.md: comprehensive technical documentation covering architecture, agent design, query_cv tool, HTMX integration, graceful degradation, security, and example conversations - README.md: add AI Chat Agent section with examples, ADK Go badge, updated tech stack and documentation index - doc/00-GO-DOCUMENTATION-INDEX.md: add chat agent to doc index --- README.md | 59 +++++++- doc/00-GO-DOCUMENTATION-INDEX.md | 7 + doc/28-AI-CHAT-AGENT.md | 230 +++++++++++++++++++++++++++++++ 3 files changed, 292 insertions(+), 4 deletions(-) create mode 100644 doc/28-AI-CHAT-AGENT.md diff --git a/README.md b/README.md index d05415e..5918282 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,9 @@ # CV Site - Go + HTMX -[![Go Version](https://img.shields.io/badge/Go-1.21%2B-00ADD8?logo=go)](https://go.dev/) -[![HTMX](https://img.shields.io/badge/HTMX-1.9.10-3366CC)](https://htmx.org/) +[![Go Version](https://img.shields.io/badge/Go-1.25%2B-00ADD8?logo=go)](https://go.dev/) +[![HTMX](https://img.shields.io/badge/HTMX-2.0-3366CC)](https://htmx.org/) +[![ADK Go](https://img.shields.io/badge/ADK_Go-1.0-4285F4?logo=google)](https://github.com/google/adk-go) +[![Gemini](https://img.shields.io/badge/Gemini_2.5_Flash-AI_Chat-8E75B2?logo=google)](https://aistudio.google.com/) [![License](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE) **Modern, minimal curriculum vitae website** for Juan AndrΓ©s Moreno Rubio built with **Go** and **HTMX**. @@ -19,6 +21,7 @@ A professional, bilingual CV site with server-side PDF generation, HTMX interact ## πŸ“‘ Table of Contents - [Features](#-features) +- [AI Chat Agent](#-ai-chat-agent) - [Demo](#-demo) - [Security](#-security) - [Quick Start](#-quick-start) @@ -43,6 +46,7 @@ A professional, bilingual CV site with server-side PDF generation, HTMX interact - βœ… **Zoom Control** - Adjustable zoom (25%-300%) with persistence across sessions - βœ… **Responsive** - Mobile, tablet, and desktop friendly - βœ… **JSON-Based Content** - Easy to update without touching code +- βœ… **AI Chat Agent** - Ask questions about the CV in natural language (powered by ADK Go + Gemini) - βœ… **AI Development Section** - Showcases modern AI-assisted development skills - βœ… **Fast & Lightweight** - Go backend with chromedp for PDF generation - βœ… **Privacy-Friendly Analytics** - Self-hosted analytics (no third-party data sharing) @@ -50,6 +54,50 @@ A professional, bilingual CV site with server-side PDF generation, HTMX interact - βœ… **Production Ready** - Systemd service, CI/CD workflows, deployment guides - βœ… **Developer Friendly** - Hot reload, clear code structure, comprehensive Makefile +## πŸ€– AI Chat Agent + +Visitors can ask questions about the CV through a floating chat widget β€” powered by [Google ADK Go 1.0](https://github.com/google/adk-go) and Gemini 2.5 Flash. + +### How It Works + +``` +Visitor types question β†’ HTMX POST /api/chat β†’ ADK Agent runs query_cv tool +β†’ Tool searches cached CV JSON data β†’ Agent formulates answer β†’ HTML response +``` + +### Example Questions & Answers + +| Question | Answer | +|----------|--------| +| *"How many Go projects has Juan built?"* | Lists 2 Go projects with descriptions | +| *"What companies has he worked at?"* | Lists all 11 companies | +| *"Does he have React experience?"* | Shows companies where React was used | +| *"ΒΏQuΓ© certificaciones tiene?"* | Lists certifications β€” answers in Spanish automatically | + +### Key Design Decisions + +- **Single agent, single tool** β€” the CV data is bounded; multi-agent orchestration would be over-engineering +- **Reads from the same data cache** the site uses β€” zero data duplication, always in sync +- **Graceful degradation** β€” no API key? Chat icon simply doesn't appear. Zero impact on the site +- **HTMX-native** β€” `hx-post` sends messages, responses are HTML fragments, no WebSocket needed +- **Language-aware** β€” the agent responds in whatever language the visitor writes in + +### Setup + +```bash +# Get a free API key from https://aistudio.google.com/apikey +echo "GOOGLE_API_KEY=your-key" >> .env + +# Chat icon appears automatically on next server start +go run . +``` + +**Free tier:** 15 requests/minute β€” more than enough for a personal CV site. + +**Full technical documentation:** [doc/28-AI-CHAT-AGENT.md](doc/28-AI-CHAT-AGENT.md) + +--- + ## πŸ“Έ Demo πŸ”— **Live Demo:** [https://juan.andres.morenorub.io/](https://juan.andres.morenorub.io/) @@ -187,9 +235,10 @@ No code changes needed - just refresh browser! ## 🎯 Key Technologies -- **Backend:** Go 1.21+ (stdlib `net/http`, graceful shutdown) +- **Backend:** Go 1.25+ (stdlib `net/http`, graceful shutdown) +- **AI Agent:** Google ADK Go 1.0 + Gemini 2.5 Flash (conversational CV navigator) - **PDF Generation:** chromedp (headless Chrome automation) -- **Frontend:** HTMX 1.9.10 (hypermedia-driven interactions) +- **Frontend:** HTMX 2.0 + Hyperscript (hypermedia-driven interactions) - **Styling:** Custom CSS with Quicksand font from Google Fonts - **Data:** JSON files for easy content management - **Deployment:** Systemd service, manual binary, GitHub Actions CI/CD @@ -206,6 +255,7 @@ This project includes comprehensive documentation organized by purpose: ### πŸ”§ Technical Reference - **[ARCHITECTURE.md](doc/ARCHITECTURE.md)** - System design, patterns, and technical decisions - **[API.md](doc/API.md)** - Complete HTTP API reference and HTMX integration +- **[AI-CHAT-AGENT.md](doc/28-AI-CHAT-AGENT.md)** - ADK Go agent architecture, tool design, and integration details ### πŸ“‹ Policies & Standards - **[SECURITY.md](doc/9-SECURITY.md)** - Complete security architecture, implementation, and testing guide @@ -323,6 +373,7 @@ This project is licensed under the **MIT License** - see the [LICENSE](LICENSE) ## πŸ™ Acknowledgments - **HTMX** - For making hypermedia-driven applications enjoyable +- **Google ADK Go** - For the production-grade agent framework - **chromedp** - For reliable headless Chrome automation - **Go Community** - For excellent standard library and tooling - **AI Assistance** - For accelerating development and documentation diff --git a/doc/00-GO-DOCUMENTATION-INDEX.md b/doc/00-GO-DOCUMENTATION-INDEX.md index a9d98fb..0203780 100644 --- a/doc/00-GO-DOCUMENTATION-INDEX.md +++ b/doc/00-GO-DOCUMENTATION-INDEX.md @@ -36,6 +36,13 @@ This documentation covers the core Go systems that power the CV site, with a foc - Coverage gap explanations - Best practices and CI/CD integration +5. **[AI Chat Agent](28-AI-CHAT-AGENT.md)** (~280 lines) + - ADK Go 1.0 integration architecture + - Agent definition with query_cv tool + - HTMX chat widget implementation + - Graceful degradation pattern + - Example conversations and security considerations + ## Quick Navigation ### By Feature diff --git a/doc/28-AI-CHAT-AGENT.md b/doc/28-AI-CHAT-AGENT.md new file mode 100644 index 0000000..98be3eb --- /dev/null +++ b/doc/28-AI-CHAT-AGENT.md @@ -0,0 +1,230 @@ +# 28. AI Chat Agent β€” ADK Go Integration + +## Overview + +The CV site includes an AI-powered conversational assistant that lets visitors ask natural language questions about the CV content. Built with [Google ADK Go 1.0](https://github.com/google/adk-go) (Agent Development Kit), it provides instant answers by querying the same cached JSON data that renders the site. + +**Live example:** A visitor can ask *"How many Go projects has Juan built?"* and get an accurate answer drawn directly from the CV data β€” no hallucination, no stale data. + +## Architecture + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ CV Site Server β”‚ +β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ Data Cache │────▢│ ADK Go Agent β”‚ β”‚ +β”‚ β”‚ (cv-en.json) β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ +β”‚ β”‚ (cv-es.json) β”‚ β”‚ β”‚ cv_assistant β”‚ β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ (LLM Agent) β”‚ β”‚ β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ +β”‚ β”‚ β”‚ β”‚ Tools: β”‚ β”‚ β”‚ +β”‚ β”‚ β”‚ β”‚ β”œβ”€ query_cv β”‚ β”‚ β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ (section+query) β”‚ β”‚ β”‚ +β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ +β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ POST /api/chat β”‚ β”‚ +β”‚ β”‚ (chat.Handler) β”‚ β”‚ +β”‚ β”‚ β”œβ”€ Session management β”‚ β”‚ +β”‚ β”‚ β”œβ”€ ADK Runner execution β”‚ β”‚ +β”‚ β”‚ └─ HTML fragment response (HTMX) β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β–² β”‚ +β”‚ β”‚ hx-post β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ Chat Widget (HTMX + Hyperscript) β”‚ β”‚ +β”‚ β”‚ β”œβ”€ Floating chat icon β”‚ β”‚ +β”‚ β”‚ β”œβ”€ Expandable panel β”‚ β”‚ +β”‚ β”‚ β”œβ”€ Message history β”‚ β”‚ +β”‚ β”‚ └─ Session persistence β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + β–Ό + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ Gemini 2.5 Flash β”‚ + β”‚ (Google AI) β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +## How It Works + +### 1. Agent Definition (`internal/chat/agent.go`) + +A single LLM agent (`cv_assistant`) with one tool (`query_cv`): + +```go +llmagent.New(llmagent.Config{ + Name: "cv_assistant", + Model: llm, + Instruction: `You answer questions about the CV owner's experience, + projects, skills, education, and career. + Use the query_cv tool to look up CV data before answering. + Answer in the SAME LANGUAGE the user writes in.`, + Tools: []tool.Tool{queryTool}, +}) +``` + +**Why a single agent?** The CV data is structured and bounded β€” there's no need for multi-agent orchestration. One agent with one tool is the right abstraction: simple, fast, predictable. + +### 2. The `query_cv` Tool + +The tool accepts two parameters: +- **`section`** β€” which CV section to search: `experience`, `projects`, `skills`, `education`, `languages`, `certifications`, `courses`, `awards`, `summary`, or `all` +- **`query`** β€” keyword filter (e.g., "Go", "React", "2019", "Olympic") + +The tool reads from the same `cache.DataCache` that powers the website rendering β€” zero additional I/O, zero data duplication. + +**Filtering logic:** Case-insensitive keyword matching across all relevant fields in each section (title, company, technologies, descriptions, responsibilities). + +### 3. HTTP Handler (`internal/chat/handler.go`) + +``` +POST /api/chat +Content-Type: application/x-www-form-urlencoded + +message=How many Go projects has Juan built? +session_id= +``` + +**Response:** HTML fragment for HTMX swap: +```html +
How many Go projects has Juan built?
+
+

Juan has built 2 projects that use Go:

+
    +
  • Immich Photo Manager - AI-Powered Photo Library MCP Server
  • +
  • Cmux Resurrect - Terminal Session Persistence Tool
  • +
+
+ +``` + +**Session management:** ADK Go's in-memory session service maintains conversation context. The session ID is preserved via a hidden form input, enabling follow-up questions. + +### 4. Chat Widget (HTMX + Hyperscript) + +The UI is a floating chat panel that follows the site's existing widget pattern: + +```html + + + + +
+ +
+``` + +**Key HTMX attributes:** +- `hx-post="/api/chat"` β€” sends message to the agent +- `hx-target="#chat-messages"` β€” appends response to chat history +- `hx-swap="beforeend scroll:bottom"` β€” auto-scrolls to latest message +- `hx-indicator="#chat-spinner"` β€” shows loading spinner during request + +## Graceful Degradation + +The chat feature is entirely optional. When `GOOGLE_API_KEY` is not set: + +1. `chat.NewHandler()` returns a disabled handler +2. `CVHandler` receives `chatEnabled: false` +3. Template data includes `ChatEnabled: false` +4. The chat widget template renders nothing (`{{if .ChatEnabled}}...{{end}}`) +5. No JavaScript errors, no broken UI, no hidden network requests + +**Zero impact on the site when disabled.** + +## Configuration + +### Required + +```bash +# .env +GOOGLE_API_KEY=your-gemini-api-key # From https://aistudio.google.com/apikey +``` + +### Optional + +```bash +MODEL_NAME=gemini-2.5-flash # Default model (free tier) +``` + +### Cost + +Gemini 2.5 Flash free tier: **15 requests/minute**, no credit card needed. Each chat message = 1 request. For a personal CV site, this is more than sufficient. + +## Example Conversations + +### English + +| Question | Answer | +|----------|--------| +| "How many years of experience?" | "Juan has 21 years of professional experience, starting in April 2005." | +| "What Go projects has he built?" | Lists Immich Photo Manager and Cmux Resurrect with descriptions | +| "Has he worked with React?" | Lists companies where React was used (Olympic Broadcasting, LIV Golf, etc.) | +| "Tell me about his time at SAP" | Pulls SAP experience entry with responsibilities and technologies | +| "What certifications does he have?" | Lists SAP CDC Full Training, SAP Cloud Platform, GDPR Compliance | + +### Spanish + +| Pregunta | Respuesta | +|----------|-----------| +| "ΒΏEn cuΓ‘ntas empresas ha trabajado?" | Lista las 11 empresas con nombres | +| "ΒΏQuΓ© tecnologΓ­as domina?" | CategorΓ­as de skills con proficiency levels | +| "ΒΏTiene experiencia con autenticaciΓ³n?" | Detalla SAP CDC, Gigya, sistemas de auth | + +## File Structure + +``` +internal/chat/ +β”œβ”€β”€ agent.go # LLM agent + query_cv tool + filter helpers +└── handler.go # HTTP handler + session management + response rendering + +templates/partials/widgets/ +└── chat-widget.html # HTMX chat panel template + +static/css/04-interactive/ +└── _chat.css # Chat UI styles (responsive, dark theme) +``` + +## Dependencies Added + +| Package | Purpose | Size Impact | +|---------|---------|-------------| +| `google.golang.org/adk` | Agent framework (runner, session, tools) | ~2 MB binary increase | +| `google.golang.org/genai` | Gemini API client | Included with ADK | + +## Security Considerations + +- **No personal data exposure:** The agent instruction explicitly prohibits revealing email, phone, or other contact details β€” it directs visitors to the contact form instead +- **Input sanitization:** User messages are HTML-escaped before rendering +- **Response sanitization:** Agent responses go through `formatResponse()` which escapes HTML then applies safe markdown-to-HTML conversion +- **Rate limiting:** The `/api/chat` endpoint inherits the site's middleware chain (recovery, logging, security headers) +- **Session isolation:** Each visitor gets an independent in-memory session; sessions are ephemeral and not persisted to disk + +## ADK Go Concepts Used + +| Concept | Usage | +|---------|-------| +| `llmagent.New` | Creates the CV assistant agent with instruction and tools | +| `functiontool.New` | Wraps the `query_cv` Go function as an agent-callable tool | +| `runner.Runner` | Executes the agent within the HTTP handler | +| `session.InMemoryService` | Maintains conversation context per visitor | +| `genai.NewContentFromText` | Converts user message to ADK content format | +| `event.IsFinalResponse()` | Extracts the agent's final answer from the event stream | +| `agent.RunConfig{}` | Default run configuration (non-streaming) | + +## Relation to Other Documentation + +- **[01-ARCHITECTURE.md](01-ARCHITECTURE.md)** β€” Overall system design +- **[03-API.md](03-API.md)** β€” HTTP API reference (includes `/api/chat`) +- **[14-BACKEND-HANDLERS.md](14-BACKEND-HANDLERS.md)** β€” Handler patterns +- **[23-DATA-CACHE.md](23-DATA-CACHE.md)** β€” How CV data is cached and accessed