# ProcureMind (PR-AGENT) — Project overview This document describes **what this codebase is for**, **which technologies it uses**, and **how the pieces fit together**. It complements the short setup notes in the root `README.md`. --- ## 1. Purpose **ProcureMind** is a **procurement assistant demo**: a chat-style web app that helps users describe what they need in natural language, **match that need to a structured catalogue** (UNSPSC-style commodity codes), **fill in a dynamic form** for the chosen item, and **preview purchase requisition (PR) line items**. Typical user journey: 1. User describes a need (for example, office chairs or laptops) in the chat. 2. The backend uses an **LLM with tools** to search a **local SQLite catalogue** (full-text search). The model never invents codes; it only picks from tool results. 3. The UI may show **one best match**, **several candidates to choose from**, or **“not found”** with guidance. 4. After a commodity is selected, the app loads or generates a **form schema** for that code, collects answers, and can **build PR rows** for review/export. It is aimed at **demos, pilots, and Hugging Face Spaces** — not a full enterprise procurement system (no ERP integration, approvals, or real vendor catalogs in this repo). --- ## 2. Technology stack | Layer | Technology | Role | |--------|------------|------| | **Frontend** | React 18, TypeScript | SPA: chat thread, cards, forms, tables | | **Frontend build** | Vite 5 | Dev server, HMR, production bundle | | **Styling** | Tailwind CSS 3, PostCSS, Autoprefixer | Layout and components | | **Backend** | Python 3.11, FastAPI, Uvicorn | JSON REST API under `/api` | | **AI** | OpenAI Python SDK (`openai`) | Chat completions + **function/tool calling** (default model configurable, often `gpt-4o-mini`) | | **Data / catalogue** | SQLite + **FTS5** (full-text index) | Searchable UNSPSC-derived catalogue | | **ETL** | Pandas, openpyxl | Build `unspsc.db` from Excel (`server/build_db.py`) | | **Production (Space / Docker)** | Docker multi-stage, **nginx** | Serves static React build; **reverse-proxies** `/api/` to Uvicorn on port 8000; listens on **7860** (Hugging Face convention) | **Environment:** `OPENAI_API_KEY` is required for real LLM behavior. Optional: `OPENAI_MODEL`, `UNSPSC_DB_PATH`, `UNSPSC_XLSX_PATH` (see README). --- ## 3. How it works (architecture) ### 3.1 High-level diagram ```text Browser (React) │ HTTP: /api/chat, /api/form-schema/…, /api/build-pr ▼ FastAPI (server/main.py) ├── run_agent() → OpenAI + tools → search_catalog / get_commodity (SQLite) ├── get_or_create_schema() → form fields for commodity (may call OpenAI) └── build_pr_rows() → structured PR line rows from form answers ▼ SQLite (data/unspsc.db) — built from data/unspsc-english*.xlsx ``` **Local development:** Vite proxies `/api` to `http://127.0.0.1:8000` (see `vite.config.ts`). **Docker / Hugging Face:** nginx serves the built SPA and forwards `/api/` to Uvicorn (see `nginx.conf`, `docker/start.sh`). ### 3.2 Main API surface (`server/main.py`) | Endpoint | Method | Purpose | |----------|--------|---------| | `/api/health` | GET | Liveness check | | `/api/chat` | POST | User message (and optional locked commodity code); returns JSON for UI (status, summary, candidates, analysis rows, errors) | | `/api/form-schema/{commodity_code}` | GET | JSON schema for dynamic procurement form for that code | | `/api/build-pr` | POST | Builds PR line rows from commodity code + dynamic field values + delivery options | ### 3.3 Agent (`server/agent.py`) - **System prompt** defines ProcureMind rules: search with short phrases, retry searches, return `found` / `choose` / `not_found`, never invent codes. - **Tools** expose catalogue operations (for example `search_catalog`, `get_commodity`) so the model reads the DB **only through defined functions**. - If `OPENAI_API_KEY` is missing, the API returns a structured error instead of calling OpenAI. ### 3.4 Catalogue (`server/catalog.py`, `server/build_db.py`) - Excel input follows a known UNSPSC export layout; `build_db` creates SQLite tables and an **FTS5** index for keyword search. - Runtime queries use FTS + helpers (tokenization, stopwords) so long user sentences are turned into searchable queries. ### 3.5 Frontend (`src/`) - **`App.tsx`** orchestrates chat state, thread items (analysis cards, disambiguation, forms), PR preview, and modals. - **`src/api/chat.ts`** and **`src/api/form.ts`** call the backend (optional `VITE_API_BASE` for non-default API origin). --- ## 4. Repository layout (short) | Path | Description | |------|-------------| | `src/` | React UI, components, API clients | | `server/` | FastAPI app, agent, catalog, form schema, PR lines, DB build | | `data/` | Source XLSX (LFS) and generated `unspsc.db` (after build) | | `docker/start.sh` | Starts Uvicorn + nginx in the container | | `Dockerfile` | Node build → Python runtime + nginx | | `nginx.conf` | SPA + `/api` proxy | --- ## 5. Related links - [Hugging Face Spaces config](https://huggingface.co/docs/hub/spaces-config-reference) (YAML in README frontmatter for the Space) --- *Generated for maintainers and onboarding; adjust as the product evolves.*