Beginner 11 minLegal

Legal counsel: analyze a contract without fuite

Direct response

To analyze a contract without it leaving your computer, serve a model with Ollama (Qwen 3.5 9B or Mistral Small 24B), extract the text from the PDF, and impose a rule: every flagged item must quote the passage word for word. A script then checks that the quote exists in the contract. Note Ollama's context window, set to 4,000 tokens by default with 24 GB of video memory.

A contract contains information that neither professional secrecy nor a confidentiality agreement allows you to entrust to just any online service. A local pipeline reads the PDF, flags clauses to review, and cites the relevant passages without any data leaving the workstation. This guide builds that pipeline, adds automatic citation verification, and clearly explains what the tool cannot do.

By Mohamed Meguedmi·Update 2026-09-30·Tested on Windows, macOS, and Linux

#Why a contract should not go through an online chat

A contract contains names, prices, negotiated terms, and sometimes personal data. Uploading it to a hosted AI service means sending this information to a third party, under a framework defined by its terms of use rather than by your confidentiality obligations. For lawyers, the issue is ethical: the “Ethics and AI” guide, adopted by the Conseil national des barreaux in March 2026, lists protection of professional secrecy and compliance with the GDPR among the profession's requirements. Commentators on the guide note that professional secrecy prohibits any disclosure of confidential information relating to matters or clients, including when using artificial intelligence tools.

For in-house counsel, the constraint is contractual: a confidentiality agreement signed with a partner almost never provides for its clauses to be subject to an AI provider. Professional offerings from vendors provide guarantees that data will not be reused, but those guarantees must be verified in the contract you signed, not in a slogan. Local analysis eliminates the issue: the contract text never leaves your workstation, so there is neither a processor to declare nor a transfer to justify.

!
Local does not mean reliable
Local deployment addresses confidentiality, not accuracy. A Stanford study published in 2024 on commercial U.S. legal research tools found erroneous answers in more than 17% of cases for the best-performing tools. These tools are not contract readers, but the order of magnitude is a reminder that a model that writes confidently can be wrong. Hence this guide's rule: every claim made by the model must be backed by a verifiable passage.

#An internal PDF chat without writing code

The Local AI Kit

Your private ChatGPT, free, on your own machine in an hour — LM Studio, Ollama, Open WebUI, your documents, no cloud.

  • Lifetime online access
  • PDF + files
  • Lifetime updates

Some readers only want to query contracts stored in a folder, without anything leaving the information system. There are two ways to do this. The first, without programming, is to install an interface such as Open WebUI or AnythingLLM on an internal server, connected to Ollama: upload the PDFs, ask questions, and let the tool find the relevant passages. These guides are available on the site. The second, described below, is a short script that gives you complete control over the prompt and citation verification.

The script works for analyzing one contract at a time, with precise questions. The document-search interface works for a corpus of several dozen contracts, where you might want to find, for example, all contracts containing an automatic-renewal clause. In the latter case, quality depends on document chunking and search, not just the model.

Which approach for which need
NeedApproachKey consideration
Read a 10- to 25-page contractDirect script, entire contract in contextContext window to increase in Ollama
Query 20 to 500 contractsRAG interface (Open WebUI, AnythingLLM)Chunking and retrieval quality
Compare with a model contractScript with two texts in the promptContext doubled: check the memory
Scanned contractOCR firstNoisy text distorts citations

#The minimal stack: model, PDF reader, script

Three components are enough. Ollama serves the model. A PDF reader such as pdfplumber or PyMuPDF extracts the text. A Python script of about forty lines connects everything. On the model side, two reference points in the Ollama library: Qwen 3.5 with 9 billion parameters weighs 6.6 GB and advertises a 256,000-token context; Mistral Small with 24 billion parameters weighs 14 GB and advertises 32,000 tokens. The first fits on an 8- to 12-GB card; the second requires 16 GB or more. Test both on three of your own contracts: legal French comprehension varies from one contract to another.

Context is the trap. Ollama sets the window by default based on video memory: below 24 GB, it is 4,000 tokens, far smaller than a contract. A 20-page contract contains several thousand words, or roughly fifteen thousand tokens or more depending on the layout; this is an order of magnitude to measure on your documents. Without adjustment, the beginning of the contract is silently truncated and the model answers based on only part of it. The guide to the context window explains the mechanism.

#Install the tools

Model and libraries
ollama pull qwen3.5:9b   # ou mistral-small si vous avez 16 Go de VRAM
pip install pdfplumber requests

Then check that the PDF contains selectable text: if pdfplumber returns an empty string, the file is a scan and you need to use OCR. Never create text from poor-quality OCR without telling the user, because the model’s citations won’t be verifiable.

#The system prompt for a first-pass triage assistant

The prompt defines the role, prohibitions, and format. The key point is the citation requirement: a model that must reproduce the passage it relies on hallucinates less, and you can verify the citation programmatically. The prompt below requests structured output to make this verification easier.

system_prompt.txt
Tu assistes un juriste pour un premier repérage rapide dans un contrat
commercial de droit français.

RÈGLES
- Tu ne donnes jamais d'avis juridique. Tu signales des points à examiner.
- Pour chaque point, recopie MOT POUR MOT le passage du contrat concerné.
- Si le contrat ne traite pas un sujet demandé, écris explicitement : non traité.
- Ne suppose jamais l'intention des parties. Ne complète pas un passage manquant.

FORMAT : un JSON, liste d'objets {"point": ..., "citation": ..., "pourquoi": ...}

#The complete script, with citation verification

The script reads the PDF, queries the model with expanded context, and enforces a schema-based JSON format, which the Ollama API supports through its format field. It then checks that each citation actually appears in the contract text, after normalizing whitespace. A citation that cannot be found is flagged separately: this indicates an invention or paraphrase that needs review.

analyse_contrat.py
import json, re, sys, requests, pdfplumber

SYSTEM = open('system_prompt.txt', encoding='utf-8').read()
SCHEMA = {'type': 'array', 'items': {'type': 'object',
  'properties': {'point': {'type': 'string'}, 'citation': {'type': 'string'},
                 'pourquoi': {'type': 'string'}},
  'required': ['point', 'citation', 'pourquoi']}}

def lire_pdf(chemin):
    with pdfplumber.open(chemin) as pdf:
        return '\n'.join(p.extract_text() or '' for p in pdf.pages)

def norm(s):
    return re.sub(r'\s+', ' ', s).strip().lower()

def demander(question, contrat, modele='qwen3.5:9b'):
    r = requests.post('http://localhost:11434/api/chat', json={
      'model': modele, 'stream': False, 'format': SCHEMA,
      'messages': [{'role': 'system', 'content': SYSTEM},
                   {'role': 'user', 'content': 'CONTRAT :\n' + contrat + '\n\nQUESTION : ' + question}],
      'options': {'temperature': 0.1, 'num_ctx': 24576}})
    return json.loads(r.json()['message']['content'])

if __name__ == '__main__':
    texte = lire_pdf(sys.argv[1])
    if len(texte.strip()) < 500:
        sys.exit('PDF sans texte exploitable : passer par un OCR.')
    base = norm(texte)
    for p in demander('Liste les clauses à risque pour le signataire.', texte):
        ok = norm(p['citation']) in base
        print(('[OK]  ' if ok else '[CITATION INTROUVABLE]  ') + p['point'])
        print('      ' + p['citation'][:200])
→
Why mechanical verification
The model may slightly rewrite a quotation, change a number, or merge two sentences. Word-for-word checking does not prove that the point raised is relevant, but it eliminates the most dangerous category of error: a clause that does not exist. Always reread the passage in the PDF before drawing a conclusion from it.

#The questions that surface risks

Ask precise questions rather than making a general request, one topic at a time. Each answer must cite the contract or state that the subject was not covered. Here's a starting list to adapt to your practice.

Non-concurrence
“Does the contract contain a non-compete clause? Quote it along with its duration, geographic scope, and financial consideration.”
Responsibility
“What is the limitation of liability? Is it mutual? What damages are excluded?”
Cancellation
“What are the termination terms? Is the notice period the same for both parties?”
Renewal
“Is there an automatic renewal? How much notice is required to oppose it, and in what form?”
Penalties
“List the penalties for late performance, breach, or nonperformance. Are they reciprocal?”
Applicable law
“Which law applies? Which jurisdiction is designated?”
Intellectual property
“How is ownership of deliverables handled: assignment, license, duration, territory?”
Personal data
“Does the contract provide for personal data processing? Are there subcontracting clauses?”

#Compare a contract with your usual template

If you have an approved reference model, such as your firm’s or company’s terms and conditions, comparison is more useful than reading a document in isolation: it shows what differs from your reference. The model sees two texts, which doubles the context space required: check that the window requested from Ollama is large enough; otherwise, compare clause by clause.

Comparison prompt
Compare le CONTRAT proposé au MODÈLE de référence.
Liste les écarts en trois catégories :
1. Plus favorables au signataire que le modèle
2. Moins favorables au signataire que le modèle
3. Clauses présentes dans le modèle et absentes du contrat

Pour chaque écart, recopie mot pour mot les deux passages.

MODÈLE :
<<<
[texte du modèle]
>>>

CONTRAT :
<<<
[texte du contrat]
>>>

#Test the tool on your own contracts before relying on it

Before integrating this assistant into a workflow, measure what it misses. Take five contracts you have already reviewed yourself, including one that deliberately contains a clause you know well, such as a barely noticeable automatic renewal. Ask the same list of questions, then count: the actual clauses found, the irrelevant points flagged, and the untraceable citations.

  1. 01
    Choose five known contracts
    Vary the types: service provision, supply, commercial lease, atypical employment contract. A single document type says nothing about overall robustness.
  2. 02
    Record your own measurements
    Before launching the tool, list the clauses you expect for each contract. This record is your ground truth.
  3. 03
    Compare recall and noise
    Count the expected clauses the tool found, and the number of points it flagged incorrectly. A tool that misses one clause out of three is a reminder, not a filter.
  4. 04
    Time the reread
    Measure how long it takes to review the flagged points and their citations. If this review takes almost as long as reading everything, the benefit is small.
  5. 05
    Decide on the use case
    Reserve the tool for tasks where it genuinely helps: initial triage, comparison against a template, and finding specific clauses. Avoid it for high-stakes contracts that will be read in full anyway.

#Limits and safeguards

Not a lawyer
The model does not know recent case law or the drafting nuances that change the meaning of a clause. It performs an initial screening; the decision remains with the lawyer.
Clause invention
A small model may describe a clause that is absent from the contract. Mandatory citation and script-based verification reduce this risk without eliminating it.
Long contract
Beyond what the context can handle, split the content into sections and query each part, or switch to document search. The guide to chunking strategies explains the options in detail.
Scans
An image-based PDF requires OCR. OCR output contains errors that make citation verification uncertain.
Logging
Do not store contracts or responses in unprotected files: workstation security and disk encryption are still necessary. The privacy checklist lists the items to check.
FAQ
Can you analyze a contract with AI without sending the document over the internet?+
Yes: Ollama serves a model on your machine, a PDF reader extracts the text, and a script queries the model. Nothing leaves the computer. Local deployment solves confidentiality, not accuracy: keep the rule requiring you to cite the passage, and verify every point in the contract before reaching a conclusion.
How can you chat with PDFs internally without taking contracts out of the information system?+
Install Open WebUI or AnythingLLM on an internal server, connected to Ollama, then load the PDFs. Document search finds the relevant passages, and the model answers with citations. Secure access with authentication and restrict the network: the documents stay on your infrastructure.
Which local model should you use to read contracts in French?+
Two reasonable candidates: Qwen 3.5 9B (6.6 GB, 256,000 tokens advertised) for an 8 to 12 GB card, and Mistral Small 24B (14 GB, 32,000 tokens advertised) starting at 16 GB. Compare them on three of your contracts rather than using an overall ranking.
Does a 30-page contract fit within the model's context window?+
Often yes for a 20- to 30-page contract, provided you increase the Ollama window, set by default to 4,000 tokens for less than 24 GB of video memory. Measure your document's actual token count. Beyond what memory can handle, split it into sections.
Can the model invent a clause that doesn’t exist?+
Yes, especially smaller models. The workaround is to require a verbatim citation, then verify with a script that it appears in the contract text. A citation that cannot be found indicates an invention. Always reread the passage in the PDF before drawing a conclusion from it.
Can AI analysis replace a lawyer's review?+
No. It serves as an initial filter to identify points for review, along with their passages. It does not know recent case law or the context of the negotiation. A legal professional remains responsible for the analysis, especially for significant issues or unusual clauses.
Did this guide help you?

Feedback, an error, or a clarification? Let us know—it improves the guide for everyone.