EcoAgent / AGENTS.md
OpelSpeedster's picture
Upload files
c80a686 verified
|
Raw
History Blame Contribute Delete
9.91 kB
# AGENTS.md
This file provides guidance to agents when working with code in this repository.
## Project
EcoAgent v2 β€” A Gradio Blocks web app for eco lifestyle advice, powered by **IBM Granite** (`ibm/granite-4-h-small`) via the `ibm-watsonx-ai` SDK. India-focused with 4 tabs: Chat, Dashboard, Recycling Guide, Household Profile.
**Classification:** Agentic AI Application with Prompt Engineering
**IBM Orchestrate REST API is NOT used** β€” direct SDK calls to watsonx.ai only.
## Stack
- **Runtime:** Python 3.14 via `uv` (venv at `.venv/`)
- **Package manager:** `uv` β€” always use `uv pip install` / `uv run python`, NOT bare `pip` or `python`
- **UI Framework:** Gradio 6.20 (ultra-light eco green theme)
- **AI Model:** IBM Granite 4 H Small (`ibm/granite-4-h-small`) via watsonx.ai eu-de
- **SDK:** `ibm-watsonx-ai` >= 1.1.15 (APIClient + ModelInference pattern)
- **Agent Tools:** 5 tools (Impact Calculator, Recycling Guide, Web Search, Scheme Checker, Household Profiler)
- **System Python is 3.11 (Miniconda)** β€” unrelated to this project's venv
- **Target deploy:** Hugging Face Spaces (Gradio SDK)
## Key Commands
```bash
uv pip install -r requirements.txt # install deps
uv run python app.py # run locally β†’ http://localhost:7860
```
## Critical Gotchas
- **`.env` is gitignored** β€” cannot be written by file tools. Use `Set-Content` PowerShell command instead.
- **`WATSONX_PROJECT_ID` is mandatory** β€” the SDK raises an error without it. Get it from: `https://eu-de.dataplatform.cloud.ibm.com` β†’ project β†’ Manage β†’ General β†’ Project ID.
- **Region is eu-de (Frankfurt)** β€” `WATSONX_URL=https://eu-de.ml.cloud.ibm.com`. Do not use `us-south`.
- **Model lazy-init** β€” `_get_model()` in `watsonx_client.py` initialises `ModelInference` on the first call, not at import. Import-time errors = missing env vars. First-call errors = bad project ID or model access.
- **`load_dotenv(".env")` explicit path** β€” both `app.py` and `watsonx_client.py` call this. The default `load_dotenv()` looks for `.env` by name; the explicit path ensures it works regardless of CWD.
- **Chat history format (Gradio 6.x)** β€” History uses structured content blocks: `{"role": "user", "content": [{"type": "text", "text": "..."}]}`. The `chat_submit()` function extracts text for the API call and returns structured blocks for display.
- **`dashboard_html` is defined inside the Tab 2 block** β€” it's referenced by `save_profile()` in Tab 4. Both must be inside the same `gr.Blocks` context.
- **Theme/CSS in Gradio 6.x** β€” `theme` and `css` parameters go in `demo.launch()`, NOT in `gr.Blocks()` constructor.
- **SSL_CERT_FILE** β€” The app auto-detects and sets the correct certifi path on startup.
- **Agent Mode** β€” When enabled, uses agentic loop with tool calls. Max 5 iterations to prevent infinite loops.
- **Web Search Date Fix** β€” IBM Granite ignores search results and hallucinates outdated dates. Fixed by injecting `TODAY'S DATE` into the system prompt and adding `Search conducted on: <date>` to search results. Never rely on LLM training data for time-sensitive information.
## Architecture
```
.env
└─ WATSONX_API_KEY, WATSONX_PROJECT_ID, WATSONX_URL
β”‚
β–Ό
watsonx_client.py
β”œβ”€ AGENT_INSTRUCTIONS ← 86-line system prompt (persona, tone, rules, format)
β”œβ”€ IMPACT_TABLE ← 20 actions with CO2/water/waste lookup values
β”œβ”€ PRODUCT_RECS ← static eco-product recs per material category
β”œβ”€ INDIAN_CITIES ← 15 major Indian cities for recycling guide
β”œβ”€ _get_model() ← lazy-init APIClient + ModelInference ( Granite 4 H Small )
β”œβ”€ get_eco_answer() ← multi-turn chat, builds [system]+messages list
β”œβ”€ get_recycling_guide() ← single-turn recycling lookup call
└─ compute_session_impact() ← aggregates logged actions β†’ metric dict
β”‚
β–Ό
tools.py (Agent Tools)
β”œβ”€ TOOLS ← 5 tool definitions (JSON Schema format)
β”œβ”€ SCHEMES_DB ← 8 Indian government eco schemes
β”œβ”€ execute_tool() ← routes tool calls to appropriate functions
β”œβ”€ _execute_calculate_impact() ← reuse compute_session_impact()
β”œβ”€ _execute_recycling_guide() ← reuse get_recycling_guide()
β”œβ”€ _execute_web_search() ← DuckDuckGo search (free, no API key) + date header
β”œβ”€ _execute_check_scheme() ← static lookup + web search fallback
└─ _execute_analyze_household() ← LLM-powered personalized analysis
β”‚
β–Ό
agent.py (Agentic Loop)
β”œβ”€ agent_loop() ← reason β†’ act β†’ observe β†’ repeat (max 5 iterations)
β”œβ”€ AGENT_SYSTEM_PROMPT ← tool usage rules + TODAY'S DATE injection + search trust rules
β”œβ”€ _extract_tool_call() ← parses JSON tool calls from LLM response
└─ format_tool_calls() ← formats tool usage for UI display
β”‚
β–Ό
app.py (Gradio Blocks β€” ultra-light theme)
β”œβ”€ Tab 1: Chat ← chatbot + Agent Mode toggle + tool display + action chips
β”œβ”€ Tab 2: Dashboard ← HTML metric cards from compute_session_impact()
β”œβ”€ Tab 3: Recycling ← material+city dropdowns β†’ get_recycling_guide()
└─ Tab 4: Profile ← household form β†’ profile_state (gr.State)
```
## Agent Mode
### How It Works
1. User enables "Agent Mode" checkbox in Chat tab
2. User sends a message
3. Agent loop begins (max 5 iterations):
- LLM receives message + tool definitions
- LLM decides to call a tool (or gives final answer)
- If tool call: execute tool, feed result back to LLM, repeat
- If final answer: return response to user
4. Tool calls are displayed below the chatbot
### Available Tools
| Tool | Purpose | When to Use |
|------|---------|-------------|
| `calculate_impact` | Get CO2/water/waste numbers | User asks about impact, wants numbers |
| `get_recycling_guide` | City-specific recycling instructions | User asks how to recycle, where to dispose |
| `web_search` | Search latest news, schemes, services | User asks about recent events, new policies |
| `check_scheme` | Indian government scheme details | User asks about subsidies, government programs |
| `analyze_household` | Personalized action plan | User wants comprehensive recommendations |
### Agent Loop Safety
- **MAX_ITERATIONS = 5** β€” prevents infinite loops
- **MAX_TOOL_CALLS_BEFORE_SYNTHESIS = 2** β€” forces LLM to answer after 2 tool calls
- **TODAY'S DATE injection** β€” system prompt includes current date so LLM doesn't hallucinate outdated info
- **Search result date header** β€” web search results include `Search conducted on: <date>` to reinforce recency
- **Graceful degradation** β€” if tool fails, continues with error message
- **Tool call logging** β€” all tool invocations are tracked and displayed
## Environment Variables
| Variable | Source | Purpose |
|---|---|---|
| `WATSONX_API_KEY` | `.env.example` | IBM Cloud API key |
| `WATSONX_PROJECT_ID` | watsonx.ai Studio | SDK project scope β€” required |
| `WATSONX_URL` | `https://eu-de.ml.cloud.ibm.com` | eu-de watsonx.ai endpoint |
## Agentic AI Pattern
This project uses **agentic AI** to transform IBM Granite into a domain-specific eco advisor with tool use:
- **System Prompt:** 86-line `AGENT_INSTRUCTIONS` + tool usage instructions
- **Tool Definitions:** 5 tools with JSON Schema parameters
- **Agent Loop:** Multi-step reasoning with tool execution
- **Static Knowledge:** `IMPACT_TABLE` (20 eco actions) and `PRODUCT_RECS` (8 material categories)
- **Dynamic Context:** Household profile (members, location, habits) injected per session
- **Tool Execution:** Real-time tool calls with result feedback
- **Output Format:** Fixed 4-part structure (Quick Tip β†’ Why it Matters β†’ Impact β†’ Optional Resource)
- **Guardrails:** Never invent stats, label [Lookup] vs [Estimate], no medical/financial advice
## Prompt Engineering Pattern
This project uses **prompt engineering** to transform IBM Granite into a domain-specific eco advisor:
- **System Prompt:** 86-line `AGENT_INSTRUCTIONS` defining persona, output format, focus areas, and guardrails
- **Static Knowledge:** `IMPACT_TABLE` (20 eco actions) and `PRODUCT_RECS` (8 material categories) injected via prompt
- **Dynamic Context:** Household profile (members, location, habits) injected per session
- **Output Format:** Fixed 4-part structure (Quick Tip β†’ Why it Matters β†’ Impact β†’ Optional Resource)
- **Guardrails:** Never invent stats, label [Lookup] vs [Estimate], no medical/financial advice
## UI Theme
Ultra-light eco green theme:
- Background: `#fcfcfd` (near white)
- Primary accent: `#2e7d50` (green)
- Cards: `#ffffff` with subtle shadows
- Text: `#1c1c1e` (near black), muted: `#4a4a4e`
- Borders: `#e4e4e7` (light gray)
- CheckboxGroup styled as selectable pills/chips
- Chatbot with welcome placeholder and white-flash prevention CSS
## Project Files
| File | Purpose |
|---|---|
| `app.py` | Gradio Blocks UI β€” 4 tabs, callbacks, CSS theme |
| `watsonx_client.py` | IBM watsonx.ai SDK wrapper, agent config, impact data |
| `tools.py` | Agent tool definitions, executor, scheme database |
| `agent.py` | Agentic loop with multi-step reasoning |
| `requirements.txt` | Pinned Python dependencies (5 packages) |
| `.env` | Local credentials (gitignored) |
| `.env.example` | Template β€” safe to commit |
| `AGENTS.md` | This file β€” agent guidance |
| `README.md` | HF Spaces front-matter, setup instructions |
| `ecoagent-plan.md` | Implementation plan and architecture decisions |
| `architecture.png` | Architecture blueprint diagram |
| `fill.txt` | PPT content fill for presentation |
## Deleted Files (v1 β†’ v2)
- `rag_pipeline.py` β†’ replaced by `watsonx_client.py`
- `ibm-credentials.env` β†’ replaced by `.env`
- `embed.txt` β†’ was a debugging artifact; deleted