# PartnerLogic

Private document intelligence prototype for **MLT Aikins**. Dark-themed RAG over a local PDF: Vertex embeddings, pgvector retrieval, Gemini 1.5 Pro synthesis, grounded answers only.

The nav reads **PartnerLogic | MLT Aikins Private Instance**. The west-pointing mark is a restrained cue to the firm’s K-arrow, not a logo reproduction.

## Stack

- FastAPI + a static HTML/CSS/JS client
- PostgreSQL 16 with `pgvector`
- Vertex AI via the Google Gen AI SDK (`vertexai=True`): `text-embedding-004` (768-d) and `gemini-1.5-pro`
- Hardcoded PoC ingest: one local PDF, 500-token chunks, 50-token overlap, top-3 cosine search

## Quick start

```bash
cp .env.example .env
# set GCP_PROJECT_ID and GOOGLE_APPLICATION_CREDENTIALS

python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt

docker compose up -d

python scripts/generate_sample_pdf.py
python scripts/ingest.py

uvicorn app.main:app --reload --host 127.0.0.1 --port 8000
```

Open [http://127.0.0.1:8000](http://127.0.0.1:8000). To ingest a real closing document instead of the specimen:

```bash
python scripts/ingest.py --pdf /path/to/shareholder_agreement.pdf
```

If Postgres already exists, run `sql/migration.sql` once (`CREATE EXTENSION vector` requires a superuser or a role with that privilege).

Without Docker, point `DATABASE_URL` at any PostgreSQL 16 instance with pgvector installed, then apply the same SQL.

## What the `/search` route does

1. Embeds the question with Vertex (`RETRIEVAL_QUERY`).
2. Retrieves the top 3 chunks with cosine distance (`ORDER BY embedding <=> query`).
3. Sends those chunks to Gemini 1.5 Pro with a strict grounding instruction.
4. Returns `{ "answer", "sources" }` to the UI.

If the chunks do not contain the answer, the model is instructed to reply:

> This is not covered in the provided document.

## GCP

Enable the Vertex AI API. Use a service account with **Vertex AI User**. Point `GOOGLE_APPLICATION_CREDENTIALS` at the JSON key. `GCP_LOCATION` defaults to `us-central1`. If `gemini-1.5-pro` is unavailable in the project, set `VERTEX_GENERATION_MODEL` to a current Gemini Pro model on Vertex.

## Specimen document

`scripts/generate_sample_pdf.py` writes a Western Canadian unanimous shareholder agreement (Prairie Harvest Holdings Inc.) so the demo can run before a client PDF is supplied. It is not a client document and is not legal advice.

Try:

- What is the right of first refusal process?
- Who sits on the Board?
- What is the drag-along threshold?
- How does the shotgun clause work?
- What is the non-compete period and territory?
- What law governs this agreement?
