Skip to content

Latest commit

 

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🤝 DealDesk

CI Python 3.11+ License: MIT

AI agent that evaluates B2B sales offers against a company's pricing policy and contract history. A sales rep enters the offer parameters; the system retrieves similar past contracts (RAG) and returns a recommendation — approve / escalate / counter-propose — with reasoning and precedent citations. Cuts offer review time from minutes to seconds.

Portfolio project. Priority: a working end-to-end demo (UI + result), not production scalability. UI and synthetic data are in Polish (realistic B2B domain); code and docs are in English.

DealDesk result view

How it works

flowchart LR
    UI[Streamlit UI] --> EV[evaluator.py]
    EV --> RT[retriever.py]
    RT --> DB[(Chroma\nvector DB)]
    EV --> LLM[llm_client.py]
    LLM --> API[Claude API\nstructured output]
    EV --> OUT[EvaluationResult\ndecision + reasoning + precedents]
    OUT --> UI
Loading
  1. Ingest — 45 synthetic contracts (metadata + full text + decision notes) are embedded (text-embedding-3-small) and stored in a local Chroma collection with numeric metadata payloads.
  2. Retrieve — hybrid search: metadata pre-filter (comparable volume band) + vector similarity over the offer description, with fallback to pure similarity search.
  3. Evaluate — Claude receives the pricing policy, retrieved precedents (with decision notes), and the new offer; output is forced through native tool use and validated with Pydantic.
  4. Explain — the UI renders the decision badge, reasoning with precedent IDs, policy flags, and expandable previews of the cited contracts.

Quick start — zero API keys (demo mode)

git clone https://github.com/HubskiIT/dealdesk && cd dealdesk
python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt

DEALDESK_DEMO=1 streamlit run app/main.py

Demo mode replaces the two external calls with local equivalents (parameter-based retrieval + rule-based decisions from pipeline/policy.py), so the whole flow runs offline on the committed sample dataset. It doubles as a transparent rule baseline for the LLM.

Full pipeline (RAG + Claude)

cp .env.example .env   # fill in ANTHROPIC_API_KEY and OPENAI_API_KEY

python scripts/generate_synthetic_data.py   # regenerate data via Claude (optional; sample data is committed)
python scripts/build_index.py               # embed + index into Chroma
streamlit run app/main.py

Evaluation

DEALDESK_DEMO=1 python eval/run_eval.py     # rule baseline, no keys needed (also runs in CI)
python eval/run_eval.py                     # full LLM pipeline

18 test offers (data/test_cases.csv) with expected decisions, including edge cases at policy boundaries. Expectations are calibrated against the committed dataset — each non-obvious label cites the precedent contract IDs that justify it.

Variant Accuracy
Rule baseline (demo mode) 94.4% (17/18)
RAG + Claude run python eval/run_eval.py with keys

The baseline's one miss (T10: a discount at the exact 20% policy boundary, where the nearest precedent is 18.3%) is a documented limitation of hard rules — the case an LLM should handle better.

Tests

pytest tests/

12 unit tests covering policy thresholds, schema validation, and the demo-mode pipeline end-to-end — no API calls. CI runs them plus the demo-mode eval on every push.

Pricing policy (summary)

Condition Default decision
Discount ≤ 10% auto-approve
Discount 10–20% requires a precedent with comparable volume, else escalate
Discount > 20% escalate, unless volume > 500 units and payment terms ≤ 30 days
Payment terms > 60 days financial-risk flag regardless of discount

Full rules in pipeline/policy.py — shared by the LLM prompt, the rule baseline, and the synthetic data generator.

Repo structure

dealdesk/
├── data/
│   ├── raw_contracts/       # 45 synthetic contracts (.txt, Polish) — committed sample
│   ├── contracts.csv        # contract metadata
│   └── test_cases.csv       # 18 test offers + expected decisions
├── pipeline/
│   ├── policy.py            # pricing policy thresholds and flags
│   ├── schema.py            # Pydantic models (Offer, EvaluationResult, ...)
│   ├── embeddings.py        # embedding client (OpenAI; swappable seam)
│   ├── ingest.py            # CSV + text -> embeddings -> Chroma
│   ├── retriever.py         # hybrid similarity search
│   ├── llm_client.py        # Claude wrapper (forced tool use + Pydantic validation)
│   ├── evaluator.py         # orchestration: retrieve -> prompt -> validate
│   └── demo.py              # zero-API demo mode / rule baseline
├── app/main.py              # Streamlit UI
├── scripts/                 # data generation + index build
├── eval/run_eval.py         # accuracy harness -> eval/eval_report.md
├── tests/                   # unit tests (no API calls)
└── .github/workflows/ci.yml # pytest + demo-mode eval

Data privacy

All contract data is synthetic (fictional companies, generated content) — safe to commit and to send to APIs. Data flow:

  • Stays local: the Chroma vector store (.chroma/), API keys (.env, gitignored).
  • Sent to OpenAI: contract texts and offer descriptions, for embeddings (full pipeline only).
  • Sent to Anthropic: retrieved precedents and the evaluated offer (full pipeline only).
  • Demo mode sends nothing anywhere — no network calls at all.

If this were adapted to real contract data, the embedding seam (pipeline/embeddings.py) allows swapping in a local model, and both API vendors offer zero-retention enterprise terms.

Design decisions

  • Chroma over Qdrant — file-based, zero setup; right-sized for a demo.
  • Forced tool use over free-text JSON — schema enforcement at the API level plus Pydantic validation with one retry carrying the validation error back to the model.
  • Hybrid retrieval — pure vector similarity ranks by topic, not by numeric closeness of discount/volume; the metadata pre-filter fixes that, with graceful fallback.
  • Rule baseline in the repo — makes the LLM's added value measurable instead of assumed.

Out of scope (deliberately)

Slack integration (n8n + FastAPI), real CRM integration, auth/multi-tenant, fine-tuning.

License

MIT

About

AI agent that evaluates B2B sales offers against a company's pricing policy and contract history. Retrieves similar past deals (RAG), and recommends approve / escalate / counter-propose with reasoning and precedent citations. Python, Chroma, Claude API, Streamlit.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages