Skip to content

RAG-SyntecIN PROGRESS

Question answering over the Syntec collective agreement: 172 documents split into 8,447 chunks, dense retrieval on Chroma, and a distance threshold that refuses off-topic questions before calling the LLM.

ROLE
Solo · Personal project, started from a technical-test skeleton
STACK
Python · LangChain · Chroma · FastAPI · Ollama · OpenAI API · Docker Compose · pytest
RESULT
Threshold calibration only: in-topic questions stayed below a distance of 0.701, off-topic ones above 0.780; the threshold sits at 0.74.
READING TIME
1 min read
1

Data

The Syntec collective agreement (IDCC 1486) from Légifrance: 172 documents split into 8,447 chunks, versioned in a hashed manifest.

2

What I built

Solo

  1. Ingestion and chunking: 500-character chunks with 100 characters of overlap.
  2. A Chroma index with top-3 dense retrieval, embeddings from a local model (Ollama) or OpenAI.
  3. Generation with a local model or gpt-4o-mini behind the same interface.
  4. A FastAPI /query endpoint, Docker Compose and 30 pytest tests.
  5. A labelled set of 55 questions in four classes, plus 20 held out, and the recall@k, precision@k, MRR and false-refusal metrics.
3

Key choices

Refuse before generating
If the nearest chunk is farther than a calibrated distance, the API refuses without calling the LLM.
Versioned corpus
A hashed manifest ties every chunk to a document version.
Local or hosted models
The same pipeline runs on Ollama or on OpenAI.
4

Results

0.6 0.9 In-topic, largest distance0.701Refusal threshold0.740Off-topic, smallest distance0.780
Calibration script on 3 in-topic and 3 off-topic questions (8 Sept 2026). Too small a sample to trust the exact boundary.

Threshold calibration only: in-topic questions stayed below a distance of 0.701, off-topic ones above 0.780; the threshold sits at 0.74.

5

Limits

  • No retrieval evaluation has run yet: the question set and the metrics exist, the runner does not.
  • Dense retrieval only: hybrid search and reranking are planned, not built.
  • The refusal threshold rests on six questions.

Questions about this project? → Email me