LLM & RAG

Your documents become a knowledge base you can query in plain language, with sourced answers.

AI only has value when it's grounded in your business. I turn your contracts, procedures and records into a base you query in plain language, and every answer cites its sources. No more hours of searching, no more made-up answers. On a simple question, the answer comes back right away; on a complex one, the system searches in several passes, cross-checks what it finds and verifies its answer before giving it to you, instead of inventing. And when it becomes a copilot for your team, each person only sees what they're already allowed to see: the copilot respects your permissions, it doesn't bypass them.

Key facts

2s

the order of magnitude targeted for a sourced answer

0

manual rekeying on extracted documents

0

made-up answers tolerated in production

LLM & RAG

What I build

01

Internal copilot & document RAG

Contracts, procedures, records: your documents become a copilot you query in plain language, with sourced answers. On easy questions, a direct answer; on hard ones, the system searches in several passes, cross-checks the documents and checks its answer before showing it. Your team stops searching, and each person only gets answers on what they're already allowed to see.

Internal copilot · Sourced answers · Iterative retrieval · Permissions respected

02

Document reading and extraction

Invoices, contracts, purchase orders, forms: your documents are read by models that understand the layout as much as the text. The right data comes out structured, ready to drop into your tool, even on PDFs that are scanned, stamped or badly framed.

Extraction · Vision · Invoices & contracts · Structuring

03

Model selection and integration

The right model for each task (Claude, GPT, open-source), cleanly plugged into your systems.

Claude · OpenAI · Open-source · MCP

The promise

The right answer, sourced and cross-checked, in seconds.

Demonstration

Coverage settled on the version that applies

A group insurance broker. A contract handler has to say whether a procedure is covered, and the answer sits in policy terms dozens of pages long, which exist in several versions depending on the contract's effective date.

Invented caseThis case is not an engagement. It is invented end to end, and the code below is the real code that would run it.

  1. HumanThe handler's request

    A member under contract CT-48213 asks whether their dental implant is covered, and up to what annual cap.

  2. The agentPicking the version

    Two sets of policy terms exist for this benefit. The contract's effective date decides which one governs. The record says 1 June 2022. I pass that date to the filter before searching anything.

  3. Tool callSearching the policy terms

    {
      "name": "search_policy_terms",
      "arguments": {
        "contract_id": "CT-48213",
        "effective_date": "2022-06-01",
        "question": "dental implant: coverage, annual cap, waiting period",
        "threshold": 0.62,
        "k": 3
      }
    }

    The threshold and the effective date travel inside the call, not as instructions in a prompt.

  4. Tool responsePassages and scores

    {
      "contract_id": "CT-48213",
      "effective_date": "2022-06-01",
      "applicable_version": "CG-2021-09",
      "threshold": 0.62,
      "excluded": [
        {
          "article": "9.1 Implantology and periodontology",
          "page": 41,
          "score": 0.84,
          "version": "CG-2024-01",
          "reason": "outside the contract period"
        }
      ],
      "below_threshold": [
        {
          "article": "12.4 Annual caps on dental benefits",
          "page": 58,
          "score": 0.57
        }
      ],
      "status": "answered",
      "sources": [
        {
          "article": "7.3 Dental, implantology",
          "page": 34,
          "score": 0.78,
          "excerpt": "Implant procedures are covered under the dental allowance set out in the schedule of benefits."
        },
        {
          "article": "4.2 Waiting periods",
          "page": 18,
          "score": 0.71,
          "excerpt": "Implant procedures qualify for reimbursement after six months of continuous membership."
        },
        {
          "article": "7.4 Supporting documents",
          "page": 35,
          "score": 0.66,
          "excerpt": "Coverage is conditional on sending the dental quote before the procedure is carried out."
        }
      ],
      "action": "escalate to handler"
    }

    The top-scoring passage comes from the version that took effect after this contract. The filter drops it before ranking.

  5. The agentThreshold check

    Three passages from the applicable version clear the 0.62 threshold. The one covering the annual cap stays under, at 0.57, so I do not state it. I answer on coverage, and the action field sends the cap back to the handler.

    With no passage above the threshold, the function refuses and escalates. It never fills in a missing passage.

  6. AnswerSourced answer

    The dental implant is covered under the dental allowance, article 7.3, page 34 of policy terms CG-2021-09, the version applicable to contract CT-48213 since 1 June 2022. Entitlement opens after six months of continuous membership, article 4.2, page 18. The quote must be sent before the procedure, article 7.4, page 35. The annual cap is not settled: the only passage covering it stays under the threshold, so that question goes back to the handler.

The codesearch_policy_terms.pypython

The search filtered to the applicable version

from dataclasses import dataclass
from datetime import date

THRESHOLD = 0.62


@dataclass(frozen=True)
class Passage:
    version: str
    article: str
    page: int
    excerpt: str
    score: float


def applicable_version(effective_date: date, periods: dict) -> str:
    for name, (start, end) in periods.items():
        if start <= effective_date <= end:
            return name
    raise LookupError("no version of the terms covers " + effective_date.isoformat())


def _cite(p: Passage) -> dict:
    return {"article": p.article, "page": p.page, "score": round(p.score, 2)}


def search_policy_terms(contract_id, question, effective_date, periods, index,
                        threshold=THRESHOLD, k=3):
    version = applicable_version(effective_date, periods)
    found = index(question)
    wrong_version = [p for p in found if p.version != version]
    candidates = [p for p in found if p.version == version]
    above = [p for p in candidates if p.score >= threshold]
    below_threshold = [p for p in candidates if p.score < threshold]
    kept = sorted(above, key=lambda p: -p.score)[:k]
    common = {
        "contract_id": contract_id,
        "effective_date": effective_date.isoformat(),
        "applicable_version": version,
        "threshold": threshold,
        "excluded": [
            dict(_cite(p), version=p.version, reason="outside the contract period")
            for p in wrong_version
        ],
        "below_threshold": [_cite(p) for p in below_threshold],
    }
    # With no passage above the threshold, an answer would be a plausible invention.
    if not kept:
        return dict(common, status="refused", action="escalate to handler")
    sources = [dict(_cite(p), excerpt=p.excerpt) for p in kept]
    action = "escalate to handler" if below_threshold else "none"
    return dict(common, status="answered", sources=sources, action=action)

Without a version filter and a refusal threshold, a document assistant is right most of the time. That is exactly what makes it unusable in contract administration.

LLM & RAG

Before / after

LLM & RAG

The stack

Claude

OpenAI

RAG

pgvector

Qdrant

Embeddings

Reranking

Python

Vision

OCR

Agentic RAG

LLM & RAG

Straight answers

01

How long does it take to set up a RAG system?

A POC on a subset of your documents takes a few weeks. A full production RAG, with corpus cleanup, evals and deployment, takes weeks to a few months depending on the volume and state of your documents.

02

Can a RAG system hallucinate?

Far less than a bare LLM, but yes, without guardrails. That's why every answer cites its sources, questions outside the corpus are declined, and I measure the rate of correct answers with evals before every release.

03

Do my documents stay confidential?

Yes. Depending on your constraints, the RAG runs on an EU cloud or entirely inside your infrastructure with private models. Your documents are never used to train public models.

04

Which documents can be plugged in?

PDFs, Word files, emails, internal wikis, business databases: anything with text can be indexed. The real issue isn't the format, it's the quality of the corpus: I sort, deduplicate and date everything before indexing.

05

How does the AI answer a complex or multi-part question?

It doesn't jump on the first page it finds. The system breaks the question down, searches your documents in several passes, cross-checks the results, then rereads its own answer to make sure it holds before giving it to you. In practice, fewer partial or made-up answers on the cases that really matter, and an answer always tied to its sources so you can check it.

06

Doesn't an internal copilot risk exposing the wrong documents?

That's the real blocker on this kind of project, and it's a design criterion from the start. The copilot respects your existing access rights: on every question, it checks what the person is allowed to see before answering, instead of freezing permissions once and for all. A salesperson doesn't stumble onto HR files, an intern doesn't surface executive contracts.

07

Do you only read text, or scanned documents too?

Both. The old approach (character recognition plus rules) breaks the moment a document changes format or comes in crooked. I use models that read the layout the way a human would: they spot a total, a due date or a clause even when it's never in the same place. In practice, your supplier invoices, contracts and scanned forms come out as clean data, verified and ready to enter your system. Mandatory electronic invoicing started in September 2026, which makes it a project that pays off fast.

Read on this topic

Contact

Ready to go from demo to production?

Reply within 24 hours · first conversation free, no strings attached.