Spaces:
Paused
Paused
| # 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 | |