Daniel StoyanovLexOpenAI SDK · Python
conversationalOpenAI SDK · PythonEmbedding retrieval + citation-constrained generation

Grounded contract counsel

Lex

Answers only what the documents support

A document-grounded research chatbot over a contract set. Lex retrieves passages by embedding similarity, answers strictly from what it retrieved, and attaches a citation to every claim.

Part I

What makes it special

  1. 1

    It declines rather than guesses

    When no retrieved passage reaches the answer floor of 0.38, Lex stops before generation and says the documents do not support an answer. The refusal shows the best scores it did find and quotes each contract’s own note on what it leaves out.

    lex/agent.py · refusal“These documents do not support an answer to this, so I am not going to give one.”
  2. 2

    Every claim names its clause

    Answers cite as [MSA clause 7.2] beside the sentence they support, and the demo sets each one as a margin note quoting the clause. An audit then checks every citation against the index: a clause that does not exist is flagged, and an answer with no valid citation is withheld.

    lex/agent.py · citation audit“An uncited answer from a grounded assistant is worse than no answer.”
  3. 3

    Retrieval you can read

    No framework and no vector database. The contracts are split on their own clause numbering, one chunk per sub-clause, so a proviso stays with the clause it qualifies. Similarity is one numpy matrix product, and every search returns its raw scores for you to see.

    README · architecture“One chunk, one locator, one citation.”
  4. 4

    It corrects its own wrong guess

    Ask fetch_clause for a clause that is not there and it returns ClauseNotFound with the list that is. In the third question Lex guesses DPA clause 11.2, reads the miss, and searches for the text instead of guessing again.

    lex/agent.py · system prompt“…read the list of available clauses it returns and search again instead of guessing a second time.”

Part II - on the docket

Inside the demo

3 questions over the same two contracts.

  1. No. 1Terminate mid-SOW?One clause, and the proviso in its second half reverses the answer.
  2. No. 2Governing law in Singapore?Outside the corpus: nothing clears the floor, so Lex refuses and shows the scores.
  3. No. 3Cap vs. breach noticeSpans both documents, and a guessed clause locator comes back not-found mid-run.

Part III - apparatus

Under the hood

How Lex is built

Stack
OpenAI SDK · Python
Pattern
Embedding retrieval + citation-constrained generation

Why this architecture

A hand-built RAG pipeline keeps retrieval inspectable: you can see the chunker, the index, the similarity scores and the exact passages that reached the model. No framework hides the step that is most likely to be the reason an answer is wrong.

Tools

  • search_corpusread-onlyRetrieve the most relevant document passages for a query, with scores.
  • fetch_clauseread-onlyFetch the full text of a numbered clause from a named document.

Real source

  • agents/lex-counsel/
  • agents/lex-counsel/lex/agent.py
  • openai
  • numpy

Before you go in

Watch for The question the corpus cannot answer. Lex returns an explicit "not supported by these documents" rather than a confident paraphrase: the behaviour that makes RAG trustworthy.

Take a look inside