Building blocks
Chat models (LLMs). Add new providers here.
BaseLLM
Common interface for chat models.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
the model name, for example "gemma3:4b". |
required |
Source code in src/rag_titan/llm/base_llm.py
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | |
ask(instructions, user_input)
Shortcut for a single question with a system instruction.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
instructions
|
the system prompt. |
required | |
user_input
|
the user message. |
required |
Returns:
| Type | Description |
|---|---|
|
The reply text with spaces removed from both ends. |
Source code in src/rag_titan/llm/base_llm.py
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | |
chat(messages, tools=None)
Send a list of messages to the model.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
messages
|
list of {"role": ..., "content": ...} dicts. |
required | |
tools
|
optional list of plain Python functions the model may call. |
None
|
Returns:
| Type | Description |
|---|---|
|
A dict: { "content": "text reply", "tool_calls": [{"name": "add", "arguments": {"a": 1, "b": 2}}], "message": the assistant message to append to the history, } |
Source code in src/rag_titan/llm/base_llm.py
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | |
tool_result_message(tool_call, result)
Build the message that sends a tool's result back to the model.
Source code in src/rag_titan/llm/base_llm.py
38 39 40 | |
FunctionLLM
Bases: BaseLLM
A chat model made from a function.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
reply
|
function that takes the messages (a list of {"role", "content"} dicts) and returns the reply text. |
required | |
model
|
name to show for this model. |
'function'
|
Source code in src/rag_titan/llm/function_llm.py
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | |
chat(messages, tools=None)
Call the function. Tools are not supported.
Source code in src/rag_titan/llm/function_llm.py
32 33 34 35 36 37 38 39 40 41 42 43 | |
tool_result_message(tool_call, result)
Build a simple tool message (tool calls are not supported).
Source code in src/rag_titan/llm/function_llm.py
45 46 47 | |
OllamaLLM
Bases: BaseLLM
Talks to an Ollama server.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
Ollama model name, for example "gemma3:4b". |
required | |
host
|
Ollama server address. None means OLLAMA_HOST, then http://localhost:11434. |
None
|
|
think
|
turn on "thinking" for models that support it. |
False
|
Source code in src/rag_titan/llm/ollama_llm.py
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 | |
chat(messages, tools=None)
Send messages to Ollama. See BaseLLM.chat() for the reply format.
Source code in src/rag_titan/llm/ollama_llm.py
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | |
tool_result_message(tool_call, result)
Build the "tool" message Ollama expects after a tool call.
Source code in src/rag_titan/llm/ollama_llm.py
63 64 65 66 67 68 69 | |
RecordingLLM
Bases: BaseLLM
Passes every new prompt to a real LLM and remembers the reply.
A prompt asked again gets the remembered reply, like ReplayLLM would give. Models do not always answer the same, so this keeps the recording exactly what a replay will do.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
llm
|
any BaseLLM, for example an OllamaLLM. |
required |
Source code in src/rag_titan/llm/replay_llm.py
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | |
chat(messages, tools=None)
Ask the real LLM (only the first time) and save its reply under the prompt's key.
Source code in src/rag_titan/llm/replay_llm.py
43 44 45 46 47 48 49 50 51 52 | |
tool_result_message(tool_call, result)
Not used: tool calls are not recorded.
Source code in src/rag_titan/llm/replay_llm.py
54 55 56 | |
ReplayLLM
Bases: BaseLLM
Answers from recorded replies.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
replies
|
dict of {prompt key: reply text}, e.g. RecordingLLM.replies. |
required | |
model
|
name to show, e.g. the model the replies came from. |
'replay'
|
Source code in src/rag_titan/llm/replay_llm.py
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | |
chat(messages, tools=None)
Return the recorded reply for exactly these messages.
Source code in src/rag_titan/llm/replay_llm.py
75 76 77 78 79 80 81 82 83 84 | |
tool_result_message(tool_call, result)
Build a simple tool message (tool calls are not replayed).
Source code in src/rag_titan/llm/replay_llm.py
86 87 88 | |
File loaders that turn files into plain text documents.
BaseLoader
Reads one kind of file and turns it into a document dict.
Source code in src/rag_titan/loaders/base_loader.py
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | |
extract_text(path)
Return all text in the file as one string.
Source code in src/rag_titan/loaders/base_loader.py
38 39 40 | |
load(path)
Read a file and return a document dict.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
path to the file. |
required |
Returns:
| Type | Description |
|---|---|
|
{"source": file name, "file_type": ".pdf", "text": all text} |
Source code in src/rag_titan/loaders/base_loader.py
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | |
DocxLoader
Bases: BaseLoader
Reads the text of every paragraph in a .docx file.
Paragraphs are separated by a blank line, and Word headings become Markdown headings ("Heading 2" -> "## "), so chunkers can see the document's structure.
Source code in src/rag_titan/loaders/docx_loader.py
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | |
extract_text(path)
Return all non-empty paragraphs, separated by blank lines.
Source code in src/rag_titan/loaders/docx_loader.py
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | |
PdfLoader
Bases: BaseLoader
Reads the text of every page in a .pdf file.
Source code in src/rag_titan/loaders/pdf_loader.py
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | |
extract_text(path)
Return the text of all pages, separated by a page break ("\f").
Source code in src/rag_titan/loaders/pdf_loader.py
14 15 16 17 18 19 20 21 22 23 | |
TextLoader
Bases: BaseLoader
Reads .txt and .md files as they are, so Markdown headings are kept.
Source code in src/rag_titan/loaders/text_loader.py
6 7 8 9 10 11 12 13 14 | |
extract_text(path)
Return the file's text. Bytes that are not valid UTF-8 become "�" instead of failing.
Source code in src/rag_titan/loaders/text_loader.py
11 12 13 14 | |
get_loader(path)
Find the loader that can read this file.
Raises:
| Type | Description |
|---|---|
ValueError
|
when no loader supports the file extension. |
Source code in src/rag_titan/loaders/loader_registry.py
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | |
load_document(path)
Load any supported file and return its document dict.
Source code in src/rag_titan/loaders/loader_registry.py
36 37 38 | |
Chunkers that split documents into small pieces.
Each family of strategies lives in its own sub-folder
fixed_size/ characters, words, tokens, recursive separators (handbook section 2) structure_aware/ sentences, paragraphs, headings, pages (handbook section 3)
Everything is also exported here, so from rag_titan.chunking import WordChunker works.
BaseChunker
Splits documents into smaller pieces called chunks.
Source code in src/rag_titan/chunking/base_chunker.py
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | |
chunk(documents)
Turn a list of document dicts into a list of chunk dicts.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
documents
|
list of {"source": ..., "text": ...} dicts. |
required |
Returns:
| Type | Description |
|---|---|
|
List of {"id": "chunk_0", "source": ..., "text": ..., |
|
|
"start_offset": 0, "end_offset": 120} dicts. |
|
|
|
|
|
from (the offsets are None if it cannot be found). |
|
|
When known, chunks also get "page_numbers" (PDFs) and |
|
|
"section_path" (documents with headings). |
Source code in src/rag_titan/chunking/base_chunker.py
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | |
split_spans(text)
Return (chunk_text, start, end) for every chunk of text.
This default searches for each chunk from split_text() in the text. Chunkers that know their exact positions override it.
Source code in src/rag_titan/chunking/base_chunker.py
46 47 48 49 50 51 52 53 | |
split_text(text)
Return a list of text pieces.
Source code in src/rag_titan/chunking/base_chunker.py
55 56 57 | |
CharacterChunker
Bases: BaseChunker
Splits text into fixed-size character windows that overlap. Example: size 1000, overlap 200 -> each new chunk starts 800 characters later.
The text is kept exactly as it is (spaces and newlines included), so a chunk may start or end in the middle of a word.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
chunk_size
|
number of characters in each chunk. |
1000
|
|
overlap
|
number of characters shared by two neighbouring chunks. |
200
|
Source code in src/rag_titan/chunking/fixed_size/character_chunker.py
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | |
split_spans(text)
(chunk, start, end) for each window; window k starts at k * (chunk_size - overlap).
Source code in src/rag_titan/chunking/fixed_size/character_chunker.py
29 30 31 32 33 34 35 36 | |
split_text(text)
Return overlapping pieces of chunk_size characters each.
Source code in src/rag_titan/chunking/fixed_size/character_chunker.py
25 26 27 | |
HeadingChunker
Bases: PieceChunker
Splits Markdown text at its headings, so a chunk never mixes two sections.
Inside a section, whole paragraphs are packed up to chunk_size (then
sentences, then words, when one is too big).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
chunk_size
|
largest chunk, in characters (or tokens with a tokenizer), including the heading path. |
1000
|
|
overlap
|
whole paragraphs repeated inside a section, up to this size. |
0
|
|
include_path
|
start each chunk with its heading path, for example "Leave policy > Sick leave". The path is skipped when it would take more than half of chunk_size. |
True
|
|
tokenizer
|
optional, counts tokens instead of characters. |
None
|
Source code in src/rag_titan/chunking/structure_aware/heading_chunker.py
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | |
section_chunks(path, body, start)
Chunk one section's body; put the heading path in front of each chunk.
Source code in src/rag_titan/chunking/structure_aware/heading_chunker.py
94 95 96 97 98 99 100 101 102 103 | |
split_spans(text)
(chunk with heading path, start, end); start/end point at the section text.
Source code in src/rag_titan/chunking/structure_aware/heading_chunker.py
84 85 86 87 88 89 90 91 92 | |
split_text(text)
Return chunks that each stay inside one section.
Source code in src/rag_titan/chunking/structure_aware/heading_chunker.py
80 81 82 | |
PageChunker
Bases: PieceChunker
Chunks each page on its own, so a chunk never spans two pages; good for citing page numbers. A page that fits is one chunk; a bigger page is cut into whole paragraphs (then sentences, then words). Empty pages are skipped. Text without page breaks (Word, Markdown) is treated as one page.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
chunk_size
|
largest chunk, in characters (or tokens with a tokenizer). |
2000
|
|
overlap
|
whole paragraphs repeated inside a page, up to this size. |
0
|
|
tokenizer
|
optional, counts tokens instead of characters. |
None
|
Source code in src/rag_titan/chunking/structure_aware/page_chunker.py
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | |
split_spans(text)
(chunk, start, end) for every chunk; positions count from the start of text.
Source code in src/rag_titan/chunking/structure_aware/page_chunker.py
32 33 34 35 36 37 38 | |
split_text(text)
Return chunks that each stay inside one page.
Source code in src/rag_titan/chunking/structure_aware/page_chunker.py
28 29 30 | |
ParagraphChunker
Bases: PieceChunker
Packs whole paragraphs (separated by a blank line) into chunks of at most
chunk_size. A paragraph that is too long is cut into sentences, and a
sentence that is still too long is cut at words.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
chunk_size
|
largest chunk, in characters (or tokens with a tokenizer). |
1000
|
|
overlap
|
whole paragraphs repeated from the previous chunk, up to this size. |
0
|
|
tokenizer
|
optional, counts tokens instead of characters. |
None
|
Source code in src/rag_titan/chunking/structure_aware/paragraph_chunker.py
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | |
pieces(text)
Paragraphs, with too-long paragraphs cut into sentences (then words).
Source code in src/rag_titan/chunking/structure_aware/paragraph_chunker.py
22 23 24 | |
sentence_pieces(paragraph)
Sentences of one paragraph, with too-long sentences cut at words.
Source code in src/rag_titan/chunking/structure_aware/paragraph_chunker.py
26 27 28 | |
RecursiveChunker
Bases: BaseChunker
Splits text on paragraphs, then lines, sentences and words, packing the
pieces into chunks of at most chunk_size characters (or tokens).
Example: size 1000, overlap 200 -> paragraphs stay whole when they fit.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
chunk_size
|
largest chunk, in characters (or tokens with a tokenizer). |
1000
|
|
overlap
|
how much of the end of a chunk is repeated at the start of the next one. Only whole pieces are repeated, so it may be less. |
200
|
|
separators
|
separators to try, biggest first. "" means a hard cut. |
SEPARATORS
|
|
tokenizer
|
optional, any object with encode(text) -> ids and decode(ids) -> text. When given, sizes count tokens. |
None
|
Source code in src/rag_titan/chunking/fixed_size/recursive_chunker.py
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | |
length(text)
Size of text in characters, or in tokens when a tokenizer is set.
Source code in src/rag_titan/chunking/fixed_size/recursive_chunker.py
55 56 57 58 59 | |
split_pieces(text)
Cut text into pieces that each fit in chunk_size, without packing them.
Joining the pieces gives back text exactly. Other chunkers use this
as a fallback for pieces that are too big.
Source code in src/rag_titan/chunking/fixed_size/recursive_chunker.py
79 80 81 82 83 84 85 | |
split_spans(text)
(chunk, start, end) for every chunk; exact, because the pieces join back into text.
Source code in src/rag_titan/chunking/fixed_size/recursive_chunker.py
65 66 67 68 69 70 71 72 73 74 75 76 77 | |
split_text(text)
Return chunks of at most chunk_size, split on the biggest separators possible.
Source code in src/rag_titan/chunking/fixed_size/recursive_chunker.py
61 62 63 | |
SentenceChunker
Bases: PieceChunker
Packs whole sentences into chunks of at most chunk_size.
A sentence is only cut (at words) when it is longer than chunk_size.
Example: size 500, overlap 100 -> chunks end at sentence boundaries and
repeat the last sentence or two of the previous chunk.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
chunk_size
|
largest chunk, in characters (or tokens with a tokenizer). |
500
|
|
overlap
|
whole sentences repeated from the previous chunk, up to this size. |
100
|
|
tokenizer
|
optional, counts tokens instead of characters. |
None
|
Source code in src/rag_titan/chunking/structure_aware/sentence_chunker.py
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | |
pieces(text)
Sentences, with too-long sentences cut at words.
Source code in src/rag_titan/chunking/structure_aware/sentence_chunker.py
23 24 25 | |
TokenChunker
Bases: BaseChunker
Splits text into fixed-size windows of model tokens that overlap. Use the same tokenizer as your embedding model, so no chunk is ever longer than the model accepts. Example: size 256, overlap 32 -> each new chunk starts 224 tokens later.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
chunk_size
|
number of tokens in each chunk. |
256
|
|
overlap
|
number of tokens shared by two neighbouring chunks. |
32
|
|
encoding
|
tiktoken encoding name, used when no tokenizer is given. |
'cl100k_base'
|
|
tokenizer
|
your own tokenizer, any object with encode(text) -> ids and decode(ids) -> text. For a Hugging Face tokenizer, wrap it so encode() calls encode(text, add_special_tokens=False). |
None
|
Source code in src/rag_titan/chunking/fixed_size/token_chunker.py
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | |
split_text(text)
Return overlapping pieces of chunk_size tokens each.
Source code in src/rag_titan/chunking/fixed_size/token_chunker.py
55 56 57 58 59 60 61 62 63 | |
WordChunker
Bases: BaseChunker
Splits text into fixed-size word windows that overlap. Example: size 150, overlap 30 -> each new chunk starts 120 words later.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
chunk_size
|
number of words in each chunk. |
150
|
|
overlap
|
number of words shared by two neighbouring chunks. |
30
|
Source code in src/rag_titan/chunking/fixed_size/word_chunker.py
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | |
split_spans(text)
(chunk, start, end): from the first word's start to the last word's end.
Source code in src/rag_titan/chunking/fixed_size/word_chunker.py
33 34 35 36 37 38 | |
split_text(text)
Return overlapping pieces of chunk_size words each.
Source code in src/rag_titan/chunking/fixed_size/word_chunker.py
29 30 31 | |
count_windows(n, size, overlap=0)
Count the windows fixed_windows() makes for n units, without making them.
Overlap repeats text, so it grows the index (handbook 2.4 "index amplification"). Compare count_windows(n, size, overlap) with count_windows(n, size, 0) to see the cost before you index anything. Formula for n > size: 1 + ceil((n - size) / (size - overlap)).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n
|
number of units (characters, words or tokens) in the text. |
required | |
size
|
number of units in each window. |
required | |
overlap
|
number of units shared by two neighbouring windows. |
0
|
Returns:
| Type | Description |
|---|---|
|
The number of windows (0 for empty text). |
Source code in src/rag_titan/chunking/fixed_size/fixed_windows.py
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | |
Embedders that turn text into vectors.
BaseEmbedder
Turns text into vectors (lists of numbers) that capture meaning.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
the embedding model name. |
required |
Source code in src/rag_titan/embeddings/base_embedder.py
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | |
embed(text)
Return one vector (numpy array) for one text.
Source code in src/rag_titan/embeddings/base_embedder.py
20 21 22 | |
embed_many(texts)
Return a list of vectors, one per text, in the same order.
Source code in src/rag_titan/embeddings/base_embedder.py
24 25 26 | |
FunctionEmbedder
Bases: BaseEmbedder
An embedder made from a function.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
embed
|
function that takes a list of texts and returns one vector (list of numbers) per text, in the same order. |
required | |
model
|
name to show for this model. |
'function'
|
Source code in src/rag_titan/embeddings/function_embedder.py
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | |
embed_many(texts)
Call the function and check it gave one vector per text.
Source code in src/rag_titan/embeddings/function_embedder.py
34 35 36 37 38 39 40 41 42 43 44 | |
HashEmbedder
Bases: BaseEmbedder
Turns text into word-count vectors of a fixed size (the "hashing trick").
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dimensions
|
length of every vector; more means fewer words share a position. |
512
|
Source code in src/rag_titan/embeddings/hash_embedder.py
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | |
embed_many(texts)
Return one vector per text. The same text always gives the same vector.
Source code in src/rag_titan/embeddings/hash_embedder.py
34 35 36 | |
OllamaEmbedder
Bases: BaseEmbedder
Creates embeddings with an Ollama server.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
Ollama embedding model name. |
'nomic-embed-text'
|
|
host
|
Ollama server address. None means http://localhost:11434. |
None
|
|
batch_size
|
how many texts to send in one request. |
32
|
Source code in src/rag_titan/embeddings/ollama_embedder.py
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | |
embed_many(texts)
Return one numpy vector per text, in the same order.
Source code in src/rag_titan/embeddings/ollama_embedder.py
32 33 34 35 36 37 38 39 40 41 42 | |
RecordingEmbedder
Bases: BaseEmbedder
Passes every text to a real embedder and remembers its vector.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
embedder
|
any BaseEmbedder, for example an OllamaEmbedder. |
required | |
decimals
|
digits kept per number in |
5
|
Source code in src/rag_titan/embeddings/replay_embedder.py
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | |
embed_many(texts)
Embed new texts with the real model, save every vector, and return the saved ones.
Source code in src/rag_titan/embeddings/replay_embedder.py
40 41 42 43 44 45 46 47 48 | |
ReplayEmbedder
Bases: BaseEmbedder
Returns recorded vectors.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
vectors
|
dict of {text key: list of numbers}, e.g. RecordingEmbedder.vectors. |
required | |
model
|
name to show, e.g. the model the vectors came from. |
'replay'
|
Source code in src/rag_titan/embeddings/replay_embedder.py
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | |
embed_many(texts)
Return the recorded vector for every text, in the same order.
Source code in src/rag_titan/embeddings/replay_embedder.py
67 68 69 70 71 72 73 74 75 76 | |
Vector stores that save chunks and search them by similarity.
BaseStore
Saves chunks with their vectors and finds the most similar ones.
Source code in src/rag_titan/vector_stores/base_store.py
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | |
add(chunks, vectors)
Save chunks together with their vectors (same order).
Source code in src/rag_titan/vector_stores/base_store.py
11 12 13 | |
clear()
Remove everything from the store.
Source code in src/rag_titan/vector_stores/base_store.py
22 23 24 | |
count()
Return how many chunks are stored.
Source code in src/rag_titan/vector_stores/base_store.py
26 27 28 | |
search(query_vector, top_k=5)
Return the top_k most similar chunks, best first. Each result is the chunk dict plus a "score" key.
Source code in src/rag_titan/vector_stores/base_store.py
15 16 17 18 19 20 | |
MemoryStore
Bases: BaseStore
Keeps everything in a Python list. Good for learning and small data.
Source code in src/rag_titan/vector_stores/memory_store.py
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | |
add(chunks, vectors)
Save each chunk with its vector.
Source code in src/rag_titan/vector_stores/memory_store.py
14 15 16 17 18 19 20 | |
clear()
Remove every stored chunk.
Source code in src/rag_titan/vector_stores/memory_store.py
35 36 37 | |
count()
Return how many chunks are stored.
Source code in src/rag_titan/vector_stores/memory_store.py
39 40 41 | |
search(query_vector, top_k=5)
Compare the query with every chunk and return the best top_k.
Source code in src/rag_titan/vector_stores/memory_store.py
22 23 24 25 26 27 28 29 30 31 32 33 | |
Retrieval: find similar chunks, then rerank them.
BaseRetriever
Finds the chunks that best match a question.
Every result is a chunk dict ("id", "source", "text", offsets, ...) plus:
"score": the retriever's score, higher is better.
"retriever": the name of the retriever that found it, e.g. "dense".
"score_trace": how the score was made, e.g. {"dense": 0.83}.
A hybrid retriever would add one entry per part, e.g.
{"bm25": 7.1, "dense": 0.83, "rrf": 0.032}.
"id" and "source" are the chunk id and source id of the evidence.
Source code in src/rag_titan/retrieval/base_retriever.py
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | |
has_documents()
Return True when there is at least one chunk to search.
Source code in src/rag_titan/retrieval/base_retriever.py
30 31 32 | |
retrieve(query, top_k=5)
Return the top_k best chunks, best first.
Source code in src/rag_titan/retrieval/base_retriever.py
26 27 28 | |
DenseRetriever
Bases: BaseRetriever
Finds chunks whose vectors are similar to the question's vector.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
embedder
|
a BaseEmbedder (must be the same one used for indexing). |
required | |
store
|
a BaseStore that holds the indexed chunks. |
required | |
dedupe_overlap
|
drop a result that overlaps a better result from the same file by at least this share of the shorter chunk (0.5 = half). None keeps every result, like before 0.5.0. |
0.5
|
Source code in src/rag_titan/retrieval/dense_retriever.py
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | |
has_documents()
Return True when the store holds at least one chunk.
Source code in src/rag_titan/retrieval/dense_retriever.py
35 36 37 | |
retrieve(query, top_k=5)
Return the top_k most similar chunks, best first.
Each result is a chunk dict with "score", "retriever" and "score_trace" keys (see BaseRetriever). Near-copies of a better result are removed (see dedupe_overlap), so twice as many candidates are fetched to still return top_k different chunks.
Source code in src/rag_titan/retrieval/dense_retriever.py
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | |
overlap_fraction(a, b)
How much two chunks overlap, from 0.0 (not at all) to 1.0.
Measured as shared characters divided by the length of the shorter chunk, so a chunk fully inside another counts as 1.0. Chunks from different files, or without offsets, give 0.0.
Source code in src/rag_titan/retrieval/dedupe.py
16 17 18 19 20 21 22 23 24 25 26 27 28 29 | |
remove_duplicates(matches, min_overlap=0.5)
Keep matches best-first and drop the ones that repeat a better match.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
matches
|
search results, best first. |
required | |
min_overlap
|
drop a match that overlaps a kept one by at least this share of the shorter chunk (0.5 = half of it). |
0.5
|
Returns:
| Type | Description |
|---|---|
|
The matches that are left, in the same order. |
Source code in src/rag_titan/retrieval/dedupe.py
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | |
Rerankers that re-order retrieved chunks.
BaseReranker
Re-orders retrieved chunks so the most useful ones come first.
Source code in src/rag_titan/retrieval/rerankers/base_reranker.py
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | |
rerank(query, matches, top_n=3)
Score every match again and keep the best ones.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
query
|
the user's question. |
required | |
matches
|
list of dicts from the retriever (each has "score"). |
required | |
top_n
|
how many matches to keep. |
3
|
Returns:
| Type | Description |
|---|---|
|
The best top_n matches, each with a "rerank_score" key. |
Source code in src/rag_titan/retrieval/rerankers/base_reranker.py
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | |
score(query, match)
Return a number. Higher means more relevant.
Source code in src/rag_titan/retrieval/rerankers/base_reranker.py
35 36 37 | |
KeywordReranker
Bases: BaseReranker
Adds a small bonus for every word shared by the question and the chunk. final score = semantic score + keyword_weight * shared words
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
keyword_weight
|
bonus added for each shared word. |
0.05
|
Source code in src/rag_titan/retrieval/rerankers/keyword_reranker.py
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | |
score(query, match)
Return the semantic score plus the keyword bonus.
Source code in src/rag_titan/retrieval/rerankers/keyword_reranker.py
21 22 23 24 | |
NoReranker
Bases: BaseReranker
Keeps the retriever's order. Useful to compare against real rerankers.
Source code in src/rag_titan/retrieval/rerankers/no_reranker.py
6 7 8 9 10 11 | |
score(query, match)
Return the retriever's own score unchanged.
Source code in src/rag_titan/retrieval/rerankers/no_reranker.py
9 10 11 | |
Evaluation: measure how well a RAG system works.
Two ways to use it
evaluate_rag(), compare_setups(), evaluate_retriever() run rag-titan pipelines on test questions and score them. RAGEvaluator and the stage evaluators (ChunkEvaluator, RetrievalEvaluator, ...) score the logged outputs of any RAG system: data in, report out.
AugmentationEvaluator
Scores the chunks that were packed into the prompt for each query.
Source code in src/rag_titan/evaluation/stages/augmentation.py
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 | |
evaluate(chunks, queries, document_text=None, documents=None, max_context_tokens=None)
Score every query that has "context_ids".
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
chunks
|
all chunks: texts, or dicts with "id", "text", "start", "end", "doc_id". |
required | |
queries
|
list of dicts with "id", "context_ids" and the gold labels: "expected_evidence" (needs the source text) and/or "expected_chunk_ids". "max_context_tokens" can be set per query. |
required | |
document_text
|
the source text of a single document. |
None
|
|
documents
|
{doc_id: text} when there are several documents. |
None
|
|
max_context_tokens
|
the context budget in words, for every query. |
None
|
Returns:
| Type | Description |
|---|---|
|
{"summary": the mean of each metric, "per_query": one dict per |
|
|
query, "warnings": chunks that could not be placed in the text}. |
Source code in src/rag_titan/evaluation/stages/augmentation.py
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | |
ChunkEvaluator
Scores the output of a chunker against the source text and gold labels.
Source code in src/rag_titan/evaluation/stages/chunking.py
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 | |
evaluate(chunks, document_text=None, documents=None, expected_chunks=None, expected_evidence=None, structural_blocks=None, required_metadata=None, expected_metadata=None, size_limits=None, boundary_tolerance=0, sentence_vectors=None, chunk_vectors=None)
Score the chunks.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
chunks
|
texts, or dicts with "id", "text", "start", "end", "doc_id", "metadata". |
required | |
document_text
|
the source text of a single document. |
None
|
|
documents
|
{doc_id: text} when there are several documents. |
None
|
|
expected_chunks
|
the ideal chunks marked by a human (for boundary F1). |
None
|
|
expected_evidence
|
gold quotes or {"start", "end"} spans that must stay whole. |
None
|
|
structural_blocks
|
tables, lists or code that must stay whole (same format). |
None
|
|
required_metadata
|
keys every chunk must have, e.g. ["source", "page"]. |
None
|
|
expected_metadata
|
{chunk_id: {key: value}} of correct metadata values. |
None
|
|
size_limits
|
(min, max) words of a valid chunk. |
None
|
|
boundary_tolerance
|
characters two boundaries may be apart and still match. |
0
|
|
sentence_vectors
|
{chunk_id: [vector per sentence]} for semantic cohesion. |
None
|
|
chunk_vectors
|
{chunk_id: vector} for semantic chunk stickiness. |
None
|
Returns:
| Type | Description |
|---|---|
|
A dict of metric name -> value (None = not measured) and "warnings". |
Source code in src/rag_titan/evaluation/stages/chunking.py
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | |
EmbeddingEvaluator
Scores chunk and query vectors, and the results of a vector index.
Source code in src/rag_titan/evaluation/stages/embedding.py
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | |
evaluate(vectors, query_vectors=None, relevant_ids=None, indexed_ids=None, index_results=None, k=5)
Score the vectors.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
vectors
|
{chunk_id: vector} of every chunk. |
required | |
query_vectors
|
{query_id: vector}. |
None
|
|
relevant_ids
|
{query_id: [gold chunk ids]}. |
None
|
|
indexed_ids
|
the chunk ids really stored in your vector index. |
None
|
|
index_results
|
{query_id: [chunk ids the index returned, best first]}. |
None
|
|
k
|
how many neighbours to compare. |
5
|
Returns:
| Type | Description |
|---|---|
|
A dict of metric name -> value (None = not measured). |
Source code in src/rag_titan/evaluation/stages/embedding.py
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | |
EndToEndEvaluator
Scores the final answers, task outcomes and request telemetry.
Source code in src/rag_titan/evaluation/stages/end_to_end.py
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | |
evaluate(queries)
Score every query that has an "answer".
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
queries
|
list of dicts with "id", "answer" and any of "expected_answer", "task_success", "latency_ms", "cost_usd", "total_tokens". |
required |
Returns:
| Type | Description |
|---|---|
|
A dict of metric name -> value (None = not measured): End-to-End P95 Latency = P95(t_request to answer) Task Success Rate = #successful tasks / #labelled tasks |
Source code in src/rag_titan/evaluation/stages/end_to_end.py
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | |
GenerationEvaluator
Scores generated answers against reference answers and your labels.
Source code in src/rag_titan/evaluation/stages/generation.py
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 | |
evaluate(queries, chunks=None)
Score every query that has an "answer".
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
queries
|
list of dicts with "id", "answer" and any of: "expected_answer", "required_facts" (phrases), "citations" and "expected_citations" (source ids), "verified_claims" (list of {"supported": True/False}), "answerable" and "abstained", "task_success", "generation_latency_ms", and the context as "context" (text) or "context_ids". |
required | |
chunks
|
the chunks, needed only to turn "context_ids" into text. |
None
|
Returns:
| Type | Description |
|---|---|
|
{"summary": the mean of each metric, "per_query": one dict per query}. |
Source code in src/rag_titan/evaluation/stages/generation.py
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | |
RAGEvaluator
Runs the stage evaluators that have data, adds root-cause hints and a scorecard.
Source code in src/rag_titan/evaluation/rag_evaluator.py
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 | |
__init__(k=5, thresholds=None, scorer=None)
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
k
|
how many results to score in the ranking metrics (Recall@K, ...). |
5
|
|
thresholds
|
{metric: minimum} for the root-cause hints. |
None
|
|
scorer
|
a ScoreAggregator with your own weights, targets or stages. |
None
|
Source code in src/rag_titan/evaluation/rag_evaluator.py
47 48 49 50 51 52 53 54 55 56 | |
evaluate(chunks=None, queries=None, document_text=None, documents=None, embeddings=None, max_context_tokens=None, **chunk_options)
Evaluate every stage that has data.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
chunks
|
the chunks of your index (see ChunkEvaluator). |
None
|
|
queries
|
list of query dicts. Each stage reads its own keys: "retrieved_ids", "reranked_ids", "context_ids", "answer", ... |
None
|
|
document_text
|
the source text of a single document. |
None
|
|
documents
|
{doc_id: text} when there are several documents. |
None
|
|
embeddings
|
dict with "vectors" and optionally "query_vectors", "relevant_ids", "indexed_ids", "index_results". |
None
|
|
max_context_tokens
|
the context budget in words. |
None
|
|
**chunk_options
|
any other ChunkEvaluator input, e.g. expected_evidence=[...], size_limits=(50, 300). |
{}
|
Returns:
| Type | Description |
|---|---|
|
A report dict: one entry per evaluated stage, plus "root_causes" |
|
|
and "scorecard". |
Source code in src/rag_titan/evaluation/rag_evaluator.py
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 | |
ReportManager
One place for everything you do with a finished report.
Source code in src/rag_titan/evaluation/reports/manager.py
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | |
failed_queries(report)
Return the queries that failed a check, earliest stage first.
Source code in src/rag_titan/evaluation/reports/manager.py
74 75 76 | |
flatten(report)
Return every numeric stage metric as {"stage.metric": value}.
Source code in src/rag_titan/evaluation/reports/manager.py
61 62 63 | |
load_json(path)
Read a report saved with save_json().
Source code in src/rag_titan/evaluation/reports/manager.py
37 38 39 40 41 42 43 44 45 46 47 48 | |
markdown(report, title='RAG Pipeline Evaluation', generated=None)
Return the report as Markdown text (see to_markdown).
Source code in src/rag_titan/evaluation/reports/manager.py
50 51 52 | |
regressions(report, baseline, tolerance=0.02, latency_share=LATENCY_SHARE, latency_min_ms=LATENCY_MIN_MS)
List the metrics that got worse than in the baseline (see find_regressions).
Source code in src/rag_titan/evaluation/reports/manager.py
65 66 67 68 | |
save_json(report, path)
Write the report as JSON (folders are created) and return the path.
Source code in src/rag_titan/evaluation/reports/manager.py
30 31 32 33 34 35 | |
save_markdown(report, path, title='RAG Pipeline Evaluation')
Write the report as Markdown (folders are created) and return the path.
Source code in src/rag_titan/evaluation/reports/manager.py
54 55 56 57 58 59 | |
trends(reports)
Return the first-to-last change of every metric over reports, oldest first.
Source code in src/rag_titan/evaluation/reports/manager.py
70 71 72 | |
RerankingEvaluator
Compares the order before ("retrieved_ids") and after ("reranked_ids") reranking.
Source code in src/rag_titan/evaluation/stages/reranking.py
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | |
evaluate(queries, k=5)
Score every query that has "reranked_ids".
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
queries
|
list of dicts with "id", "reranked_ids" (best first), the gold labels ("expected_chunk_ids" or graded "relevance") and, to measure the gains, "retrieved_ids". |
required | |
k
|
how many results to score per query. |
5
|
Returns:
| Type | Description |
|---|---|
|
{"summary": the mean of each metric, "per_query": one dict per query}. |
|
|
Gains are None for a query without "retrieved_ids". |
Source code in src/rag_titan/evaluation/stages/reranking.py
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | |
RetrievalEvaluator
Scores the ranked chunk ids a retriever returned for each query.
Source code in src/rag_titan/evaluation/stages/retrieval.py
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | |
evaluate(chunks, queries, k=5, document_text=None, documents=None)
Score every query that has "retrieved_ids".
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
chunks
|
all chunks of the index: texts, or dicts with "id", "text" and, when you have them, "start", "end" and "doc_id". |
required | |
queries
|
list of dicts with "id", "retrieved_ids" (best first) and the gold labels: "expected_chunk_ids" or graded "relevance", and optionally "expected_evidence" and "retrieval_latency_ms". |
required | |
k
|
how many results to score per query. |
5
|
|
document_text
|
the source text of a single document. |
None
|
|
documents
|
{doc_id: text} when there are several documents. |
None
|
Returns:
| Type | Description |
|---|---|
|
{"summary": the mean of each metric, "per_query": one dict per |
|
|
query, "warnings": chunks that could not be placed in the text}. |
|
|
A metric is None when its inputs were not given. |
Source code in src/rag_titan/evaluation/stages/retrieval.py
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | |
RootCauseAnalyzer
Finds the metrics below their minimum and the first stage that fails.
Source code in src/rag_titan/evaluation/root_cause.py
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | |
__init__(thresholds=None)
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
thresholds
|
{metric: minimum} to change the defaults, e.g. {"recall_at_k": 0.9, "answer_f1": 0.6}. |
None
|
Source code in src/rag_titan/evaluation/root_cause.py
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | |
evaluate(report)
Check a report from RAGEvaluator (or a dict of {stage: stage result}).
Returns:
| Type | Description |
|---|---|
|
A dict with "first_failing_stage" (a stage name or None), "failures" |
|
|
(a list of {"stage", "metric", "observed", "minimum", "suggestion"}) |
|
|
and "method" (how the hints were made). Metrics that were not |
|
|
measured are skipped, not failed. |
Source code in src/rag_titan/evaluation/root_cause.py
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | |
ScoreAggregator
Combines the stage metrics into stage scores, an overall score and a status.
Source code in src/rag_titan/evaluation/scoring/scorecard.py
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 | |
__init__(stage_weights=None, metric_weights=None, targets=None, quality_gates=None, stages=None, min_coverage=0.75)
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
stage_weights
|
{stage: weight} to change how much a stage counts. |
None
|
|
metric_weights
|
{stage: {metric: weight}}; weight 0 switches a metric off. |
None
|
|
targets
|
{stage: {metric: target}} for sizes, latency and cost, e.g. {"end_to_end": {"p95_latency_ms": 2000}}. |
None
|
|
quality_gates
|
{stage: {metric: minimum}} replacing the default gates. |
None
|
|
stages
|
the stages to score, e.g. ["retrieval"]; default is all. |
None
|
|
min_coverage
|
below this measured share the score is "Provisional". |
0.75
|
Source code in src/rag_titan/evaluation/scoring/scorecard.py
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | |
evaluate(report)
Score a report from RAGEvaluator (or a dict of {stage: stage result}).
Returns:
| Type | Description |
|---|---|
|
{"overall": score, rating, status, coverage, gate failures and the |
|
|
stages to review, "stages": one entry per stage, "stage_weights", "method"}. |
Source code in src/rag_titan/evaluation/scoring/scorecard.py
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | |
as_questions(questions)
Accept a questions file path or an already loaded list, and return the checked list.
Lets every helper take either "questions.json" or [{...}, ...].
Source code in src/rag_titan/evaluation/questions.py
42 43 44 45 46 47 48 49 | |
build_dataset(chunks, runs, golden, documents, require_validated=True)
Return {"documents", "chunks", "queries", "expected_evidence"} ready for evaluation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
chunks
|
your chunks, dicts with "id" and "text" ("doc_id" when there are several documents; the text must occur in that document). |
required | |
runs
|
one dict per question your RAG answered, with "question" (or the golden "id") and its outputs: "retrieved_ids", "context_ids", "answer", latencies, ... (see RUN_KEYS). |
required | |
golden
|
golden questions, a JSON file path or a list of dicts. |
required | |
documents
|
{name: text} of the documents your chunks come from. |
required | |
require_validated
|
refuse golden questions a person has not reviewed. |
True
|
Source code in src/rag_titan/evaluation/dataset.py
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | |
check_golden(questions, documents=None)
Check a golden set before you trust the scores made with it.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
questions
|
path to a golden questions JSON file, or a list of dicts. |
required | |
documents
|
{doc_id: text}; when given, every quote must be found in them. |
None
|
Returns:
| Type | Description |
|---|---|
|
A dict with "question_count", "validated_count", "validated_share", |
|
|
"problems" (a list of {"id", "problem"}) and "ready". |
|
|
A person marks a question as checked with "validated": true. |
|
|
"ready" is True when there is no problem and every question is validated. |
Source code in src/rag_titan/evaluation/golden.py
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 | |
check_questions(records)
Check a list of question dicts and return it. Raises ValueError with the record id when something is missing or wrong.
Source code in src/rag_titan/evaluation/questions.py
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | |
collect_dataset(rag, files, questions, include_embeddings=False)
Index the files, run every golden question, and return the RAGEvaluator input.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
rag
|
a RAGTitan. |
required | |
files
|
list of file paths to index (the index is rebuilt). |
required | |
questions
|
path to a golden questions JSON file, or a list of dicts. |
required | |
include_embeddings
|
also collect the chunk and query vectors for the embedding stage (embeds every question once more). |
False
|
Returns:
| Type | Description |
|---|---|
|
A dict with "documents", "chunks", "queries" and, when asked, |
|
|
"embeddings": pass it to RAGEvaluator().evaluate(**dataset). |
Source code in src/rag_titan/evaluation/collect.py
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | |
compare_retrievers(retrievers, questions, top_k=5)
Evaluate several retrievers on identical questions and top_k.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
retrievers
|
dict of {name: retriever}, e.g. {"dense": r1, "bm25": r2}. |
required |
Returns:
| Type | Description |
|---|---|
|
A list with one evaluate_retriever() result per retriever, in order. |
Source code in src/rag_titan/evaluation/benchmark.py
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | |
compare_setups(files, questions, setups)
Index the files and evaluate every setup on the same questions.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
files
|
list of file paths to index. |
required | |
questions
|
path to a questions file, or a list of question dicts. |
required | |
setups
|
list of {"name": ..., "rag_type": "simple", "settings": {...}}. "settings" changes any setting (chunker, chunk_size, models, ...). |
required |
Returns:
| Type | Description |
|---|---|
|
A list with one evaluate_rag() result per setup, in order; each also |
|
|
has the setup's "rag_type" and "settings". |
Setups with the same settings share one index, so comparing RAG types on the same ingestion embeds the files only once.
Source code in src/rag_titan/evaluation/end_to_end.py
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 | |
evaluate_file(input_path, output_path='rag_report.json', k=5, baseline=None)
Evaluate a data file and save the report as JSON and Markdown.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
input_path
|
the JSON data file. |
required | |
output_path
|
where to write the JSON report; the Markdown report gets the same name ending in .md. |
'rag_report.json'
|
|
k
|
how many results to score in the ranking metrics. |
5
|
|
baseline
|
path of an earlier JSON report; the metrics that got worse are added to the report as "regressions". |
None
|
Returns:
| Type | Description |
|---|---|
|
The report dict. |
Source code in src/rag_titan/evaluation/reports/run.py
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | |
evaluate_rag(rag, questions, name=None)
Answer every question with rag.run() and score the run.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
rag
|
any BaseRAG (SimpleRAG, AdaptiveRAG, ...) with indexed documents. |
required | |
questions
|
path to a questions file, or a list of question dicts. |
required | |
name
|
name shown in the report, defaults to the class name. |
None
|
Returns:
| Type | Description |
|---|---|
|
A dict with the means ("recall", "mrr", "ndcg" on the sources, |
|
|
"answered" share, average "steps"), the total time per question |
|
|
("p50_s", "p95_s") and one row per question in "rows" |
|
|
(each row keeps the answer and every step). |
Source code in src/rag_titan/evaluation/end_to_end.py
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | |
evaluate_retriever(retriever, questions, top_k=5, name=None)
Ask every question and score what the retriever finds.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
retriever
|
any BaseRetriever with indexed documents. |
required | |
questions
|
list of question dicts (see load_questions). |
required | |
top_k
|
how many chunks to retrieve and score per question. |
5
|
|
name
|
name shown in the report, defaults to retriever.name. |
None
|
Returns:
| Type | Description |
|---|---|
|
A dict with the means ("recall", "mrr", "ndcg"), the latency |
|
|
("p50_ms", "p95_ms") and one row per question in "rows". |
Source code in src/rag_titan/evaluation/benchmark.py
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | |
format_rag_report(results)
Return the end-to-end results as a text table, one line per setup.
Source code in src/rag_titan/evaluation/end_to_end.py
107 108 109 110 111 112 113 114 | |
format_report(results)
Return the results as a text table, one line per retriever.
Source code in src/rag_titan/evaluation/benchmark.py
71 72 73 74 75 76 77 78 79 | |
load_golden(questions)
Return the golden questions from a JSON file path or a list, after checking them.
Source code in src/rag_titan/evaluation/golden.py
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | |
load_questions(path)
Read and check a questions file.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
path to the JSON file. |
required |
Returns:
| Type | Description |
|---|---|
|
The list of question dicts. |
Source code in src/rag_titan/evaluation/questions.py
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | |
make_golden_template(questions, documents=None)
Return one golden record per question, with empty labels to fill in.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
questions
|
a list of question texts. |
required | |
documents
|
optional {name: text}; when given, each record gets a suggested evidence sentence taken word for word from them. |
None
|
Returns:
| Type | Description |
|---|---|
|
A list of dicts with "id" (q1, q2, ...), "question", "expected_answer", |
|
|
"expected_evidence", "required_facts", "answerable", "validated" and "_todo". |
Source code in src/rag_titan/evaluation/golden_template.py
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | |
matches_evidence(chunk, evidence_id)
Return True when the chunk is (part of) the evidence.
Source code in src/rag_titan/evaluation/metrics.py
35 36 37 38 39 40 41 42 43 | |
ndcg_at_k(retrieved, required, k)
Normalised discounted cumulative gain (0 to 1): finding evidence early counts more.
DCG = Σ gain_rank / log2(rank + 1), gain = new evidences found at that rank
IDCG = the DCG of one new evidence at each of the first min(|Relevant|, k) ranks
One chunk can hold two evidences (say pages 4 and 5), which can beat the ideal, so the result is capped at 1.
Source code in src/rag_titan/evaluation/metrics.py
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | |
parse_evidence_id(evidence_id)
Split an evidence id into (source, page). page is None for a whole file.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
evidence_id
|
"hr.pdf" or "hr.pdf#p4". |
required |
Source code in src/rag_titan/evaluation/metrics.py
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | |
profile_documents(documents, min_words=20, near_duplicate=0.9)
Profile a document collection: sizes, empty and short documents, duplicates, categories.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
documents
|
{doc_id: text} or a list of document dicts. |
required | |
min_words
|
documents with fewer words are reported as "short". |
20
|
|
near_duplicate
|
two documents sharing at least this share of their words (Jaccard) are near duplicates. None skips the check, which compares every pair and is slow above a few thousand documents. |
0.9
|
Returns:
| Type | Description |
|---|---|
|
A dict with the counts and word statistics, "categories" (count per |
|
|
category), "exact_duplicates" (groups of ids), "near_duplicates" |
|
|
(pairs with their similarity), "issues" ({doc_id: [reasons]}) and |
|
|
"clean_share" (documents without any issue / all documents). |
Source code in src/rag_titan/evaluation/profiling.py
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | |
recall_at_k(retrieved, required, k)
Share of the required evidence found in the first k chunks (0 to 1).
Recall@k = |Relevant ∩ Retrieved_k| / |Relevant|
Source code in src/rag_titan/evaluation/metrics.py
63 64 65 66 67 68 69 | |
reciprocal_rank(retrieved, required, k)
1 / rank of the first chunk that is evidence, or 0 when none is in the first k. The mean of this over all questions is the MRR.
Source code in src/rag_titan/evaluation/metrics.py
72 73 74 75 76 77 78 79 80 | |
sample_documents(documents, size, strategy='random', seed=0, profile=None)
Return the ids of a sample of the documents.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
documents
|
{doc_id: text} or a list of document dicts. |
required | |
size
|
how many documents to pick (at most all of them). |
required | |
strategy
|
"random", "stratified" or "risk". |
'random'
|
|
seed
|
the random seed, for a repeatable sample. |
0
|
|
profile
|
a profile_documents() result for "risk"; made when missing. |
None
|
Source code in src/rag_titan/evaluation/sampling.py
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | |
Stage evaluators: score the logged outputs of each RAG stage against gold labels.
AugmentationEvaluator
Scores the chunks that were packed into the prompt for each query.
Source code in src/rag_titan/evaluation/stages/augmentation.py
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 | |
evaluate(chunks, queries, document_text=None, documents=None, max_context_tokens=None)
Score every query that has "context_ids".
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
chunks
|
all chunks: texts, or dicts with "id", "text", "start", "end", "doc_id". |
required | |
queries
|
list of dicts with "id", "context_ids" and the gold labels: "expected_evidence" (needs the source text) and/or "expected_chunk_ids". "max_context_tokens" can be set per query. |
required | |
document_text
|
the source text of a single document. |
None
|
|
documents
|
{doc_id: text} when there are several documents. |
None
|
|
max_context_tokens
|
the context budget in words, for every query. |
None
|
Returns:
| Type | Description |
|---|---|
|
{"summary": the mean of each metric, "per_query": one dict per |
|
|
query, "warnings": chunks that could not be placed in the text}. |
Source code in src/rag_titan/evaluation/stages/augmentation.py
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | |
ChunkEvaluator
Scores the output of a chunker against the source text and gold labels.
Source code in src/rag_titan/evaluation/stages/chunking.py
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 | |
evaluate(chunks, document_text=None, documents=None, expected_chunks=None, expected_evidence=None, structural_blocks=None, required_metadata=None, expected_metadata=None, size_limits=None, boundary_tolerance=0, sentence_vectors=None, chunk_vectors=None)
Score the chunks.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
chunks
|
texts, or dicts with "id", "text", "start", "end", "doc_id", "metadata". |
required | |
document_text
|
the source text of a single document. |
None
|
|
documents
|
{doc_id: text} when there are several documents. |
None
|
|
expected_chunks
|
the ideal chunks marked by a human (for boundary F1). |
None
|
|
expected_evidence
|
gold quotes or {"start", "end"} spans that must stay whole. |
None
|
|
structural_blocks
|
tables, lists or code that must stay whole (same format). |
None
|
|
required_metadata
|
keys every chunk must have, e.g. ["source", "page"]. |
None
|
|
expected_metadata
|
{chunk_id: {key: value}} of correct metadata values. |
None
|
|
size_limits
|
(min, max) words of a valid chunk. |
None
|
|
boundary_tolerance
|
characters two boundaries may be apart and still match. |
0
|
|
sentence_vectors
|
{chunk_id: [vector per sentence]} for semantic cohesion. |
None
|
|
chunk_vectors
|
{chunk_id: vector} for semantic chunk stickiness. |
None
|
Returns:
| Type | Description |
|---|---|
|
A dict of metric name -> value (None = not measured) and "warnings". |
Source code in src/rag_titan/evaluation/stages/chunking.py
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | |
EmbeddingEvaluator
Scores chunk and query vectors, and the results of a vector index.
Source code in src/rag_titan/evaluation/stages/embedding.py
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | |
evaluate(vectors, query_vectors=None, relevant_ids=None, indexed_ids=None, index_results=None, k=5)
Score the vectors.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
vectors
|
{chunk_id: vector} of every chunk. |
required | |
query_vectors
|
{query_id: vector}. |
None
|
|
relevant_ids
|
{query_id: [gold chunk ids]}. |
None
|
|
indexed_ids
|
the chunk ids really stored in your vector index. |
None
|
|
index_results
|
{query_id: [chunk ids the index returned, best first]}. |
None
|
|
k
|
how many neighbours to compare. |
5
|
Returns:
| Type | Description |
|---|---|
|
A dict of metric name -> value (None = not measured). |
Source code in src/rag_titan/evaluation/stages/embedding.py
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | |
EndToEndEvaluator
Scores the final answers, task outcomes and request telemetry.
Source code in src/rag_titan/evaluation/stages/end_to_end.py
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | |
evaluate(queries)
Score every query that has an "answer".
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
queries
|
list of dicts with "id", "answer" and any of "expected_answer", "task_success", "latency_ms", "cost_usd", "total_tokens". |
required |
Returns:
| Type | Description |
|---|---|
|
A dict of metric name -> value (None = not measured): End-to-End P95 Latency = P95(t_request to answer) Task Success Rate = #successful tasks / #labelled tasks |
Source code in src/rag_titan/evaluation/stages/end_to_end.py
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | |
GenerationEvaluator
Scores generated answers against reference answers and your labels.
Source code in src/rag_titan/evaluation/stages/generation.py
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 | |
evaluate(queries, chunks=None)
Score every query that has an "answer".
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
queries
|
list of dicts with "id", "answer" and any of: "expected_answer", "required_facts" (phrases), "citations" and "expected_citations" (source ids), "verified_claims" (list of {"supported": True/False}), "answerable" and "abstained", "task_success", "generation_latency_ms", and the context as "context" (text) or "context_ids". |
required | |
chunks
|
the chunks, needed only to turn "context_ids" into text. |
None
|
Returns:
| Type | Description |
|---|---|
|
{"summary": the mean of each metric, "per_query": one dict per query}. |
Source code in src/rag_titan/evaluation/stages/generation.py
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | |
RerankingEvaluator
Compares the order before ("retrieved_ids") and after ("reranked_ids") reranking.
Source code in src/rag_titan/evaluation/stages/reranking.py
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | |
evaluate(queries, k=5)
Score every query that has "reranked_ids".
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
queries
|
list of dicts with "id", "reranked_ids" (best first), the gold labels ("expected_chunk_ids" or graded "relevance") and, to measure the gains, "retrieved_ids". |
required | |
k
|
how many results to score per query. |
5
|
Returns:
| Type | Description |
|---|---|
|
{"summary": the mean of each metric, "per_query": one dict per query}. |
|
|
Gains are None for a query without "retrieved_ids". |
Source code in src/rag_titan/evaluation/stages/reranking.py
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | |
RetrievalEvaluator
Scores the ranked chunk ids a retriever returned for each query.
Source code in src/rag_titan/evaluation/stages/retrieval.py
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | |
evaluate(chunks, queries, k=5, document_text=None, documents=None)
Score every query that has "retrieved_ids".
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
chunks
|
all chunks of the index: texts, or dicts with "id", "text" and, when you have them, "start", "end" and "doc_id". |
required | |
queries
|
list of dicts with "id", "retrieved_ids" (best first) and the gold labels: "expected_chunk_ids" or graded "relevance", and optionally "expected_evidence" and "retrieval_latency_ms". |
required | |
k
|
how many results to score per query. |
5
|
|
document_text
|
the source text of a single document. |
None
|
|
documents
|
{doc_id: text} when there are several documents. |
None
|
Returns:
| Type | Description |
|---|---|
|
{"summary": the mean of each metric, "per_query": one dict per |
|
|
query, "warnings": chunks that could not be placed in the text}. |
|
|
A metric is None when its inputs were not given. |
Source code in src/rag_titan/evaluation/stages/retrieval.py
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | |
Scoring: turn stage metrics into 0 to 100 scores, ratings and quality gates.
ScoreAggregator
Combines the stage metrics into stage scores, an overall score and a status.
Source code in src/rag_titan/evaluation/scoring/scorecard.py
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 | |
__init__(stage_weights=None, metric_weights=None, targets=None, quality_gates=None, stages=None, min_coverage=0.75)
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
stage_weights
|
{stage: weight} to change how much a stage counts. |
None
|
|
metric_weights
|
{stage: {metric: weight}}; weight 0 switches a metric off. |
None
|
|
targets
|
{stage: {metric: target}} for sizes, latency and cost, e.g. {"end_to_end": {"p95_latency_ms": 2000}}. |
None
|
|
quality_gates
|
{stage: {metric: minimum}} replacing the default gates. |
None
|
|
stages
|
the stages to score, e.g. ["retrieval"]; default is all. |
None
|
|
min_coverage
|
below this measured share the score is "Provisional". |
0.75
|
Source code in src/rag_titan/evaluation/scoring/scorecard.py
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | |
evaluate(report)
Score a report from RAGEvaluator (or a dict of {stage: stage result}).
Returns:
| Type | Description |
|---|---|
|
{"overall": score, rating, status, coverage, gate failures and the |
|
|
stages to review, "stages": one entry per stage, "stage_weights", "method"}. |
Source code in src/rag_titan/evaluation/scoring/scorecard.py
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | |
rating(score)
Return (rating, meaning) for a 0 to 100 score; None means nothing was measured.
Source code in src/rag_titan/evaluation/scoring/policy.py
121 122 123 124 125 | |
Reports: save evaluation reports as JSON or Markdown and compare them over time.
ReportManager
One place for everything you do with a finished report.
Source code in src/rag_titan/evaluation/reports/manager.py
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | |
failed_queries(report)
Return the queries that failed a check, earliest stage first.
Source code in src/rag_titan/evaluation/reports/manager.py
74 75 76 | |
flatten(report)
Return every numeric stage metric as {"stage.metric": value}.
Source code in src/rag_titan/evaluation/reports/manager.py
61 62 63 | |
load_json(path)
Read a report saved with save_json().
Source code in src/rag_titan/evaluation/reports/manager.py
37 38 39 40 41 42 43 44 45 46 47 48 | |
markdown(report, title='RAG Pipeline Evaluation', generated=None)
Return the report as Markdown text (see to_markdown).
Source code in src/rag_titan/evaluation/reports/manager.py
50 51 52 | |
regressions(report, baseline, tolerance=0.02, latency_share=LATENCY_SHARE, latency_min_ms=LATENCY_MIN_MS)
List the metrics that got worse than in the baseline (see find_regressions).
Source code in src/rag_titan/evaluation/reports/manager.py
65 66 67 68 | |
save_json(report, path)
Write the report as JSON (folders are created) and return the path.
Source code in src/rag_titan/evaluation/reports/manager.py
30 31 32 33 34 35 | |
save_markdown(report, path, title='RAG Pipeline Evaluation')
Write the report as Markdown (folders are created) and return the path.
Source code in src/rag_titan/evaluation/reports/manager.py
54 55 56 57 58 59 | |
trends(reports)
Return the first-to-last change of every metric over reports, oldest first.
Source code in src/rag_titan/evaluation/reports/manager.py
70 71 72 | |
evaluate_file(input_path, output_path='rag_report.json', k=5, baseline=None)
Evaluate a data file and save the report as JSON and Markdown.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
input_path
|
the JSON data file. |
required | |
output_path
|
where to write the JSON report; the Markdown report gets the same name ending in .md. |
'rag_report.json'
|
|
k
|
how many results to score in the ranking metrics. |
5
|
|
baseline
|
path of an earlier JSON report; the metrics that got worse are added to the report as "regressions". |
None
|
Returns:
| Type | Description |
|---|---|
|
The report dict. |
Source code in src/rag_titan/evaluation/reports/run.py
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | |
failed_queries(report)
Return [{"query_id", "stage", "reason"}] for the queries that failed a check.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
report
|
a report from RAGEvaluator. |
required |
Source code in src/rag_titan/evaluation/reports/failures.py
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | |
find_regressions(report, baseline, tolerance=0.02, latency_share=LATENCY_SHARE, latency_min_ms=LATENCY_MIN_MS)
List the metrics that got worse than in the baseline report.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
report
|
the new report. |
required | |
baseline
|
an earlier report to compare with. |
required | |
tolerance
|
how much worse still counts as noise. For scores it is an absolute change (0.02 = 2 points of 100); for latency, cost and tokens a relative one (0.02 = 2% slower or more expensive). |
0.02
|
|
latency_share
|
a latency must also be this share slower (0.10 = 10%). |
LATENCY_SHARE
|
|
latency_min_ms
|
... and this many milliseconds slower. Set both to 0 to count every slower timing. |
LATENCY_MIN_MS
|
Returns:
| Type | Description |
|---|---|
|
A list of {"metric", "baseline", "current", "delta"}, in pipeline order. |
Source code in src/rag_titan/evaluation/reports/compare.py
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | |
flatten(report)
Return every numeric stage metric of a report as {"stage.metric": value}.
Source code in src/rag_titan/evaluation/reports/compare.py
25 26 27 28 29 30 31 32 33 34 35 36 37 38 | |
summary_text(report)
Return the lines printed after an evaluation: score, status, first failure, the queries to look at, regressions and what was not measured.
Source code in src/rag_titan/evaluation/reports/run.py
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | |
to_markdown(report, title='RAG Pipeline Evaluation', generated=None)
Return the report as Markdown text.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
report
|
a report from RAGEvaluator. A "regressions" entry is shown when present. |
required | |
title
|
the heading of the report. |
'RAG Pipeline Evaluation'
|
|
generated
|
the timestamp text; default is the current UTC time. |
None
|
Source code in src/rag_titan/evaluation/reports/markdown.py
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | |
trends(reports)
Return the change of every metric from the first to the last report.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
reports
|
report dicts, oldest first. |
required |
Returns:
| Type | Description |
|---|---|
|
{"stage.metric": {"first", "last", "change", "improved", "runs"}} for the |
|
|
metrics present in every report. "improved" is None when neither |
|
|
direction is better. Empty with fewer than two reports. |
Source code in src/rag_titan/evaluation/reports/compare.py
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 | |
Generators that write the final answer.
BaseGenerator
Writes the final answer from the question and the chosen chunks.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
llm
|
any BaseLLM. |
required | |
instructions
|
the system prompt for the LLM. |
required |
Source code in src/rag_titan/generation/base_generator.py
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | |
generate(query, chunks)
Return the final answer text for the question.
Source code in src/rag_titan/generation/base_generator.py
23 24 25 | |
GroundedGenerator
Bases: BaseGenerator
Answers only from the given chunks and cites their ids.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
llm
|
any BaseLLM. |
required | |
instructions
|
system prompt, defaults to GROUNDED_ANSWER_PROMPT. |
GROUNDED_ANSWER_PROMPT
|
Source code in src/rag_titan/generation/grounded_generator.py
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | |
generate(query, chunks)
Return an answer with citations, or NO_ANSWER when unsure.
Source code in src/rag_titan/generation/grounded_generator.py
19 20 21 22 23 24 25 26 27 | |
build_context(chunks)
Join chunks into one text block the LLM can read and cite.
Each chunk looks like
[chunk_3] Source: handbook.pdf, page 2 ...chunk text...
Source code in src/rag_titan/generation/context_builder.py
23 24 25 26 27 28 29 30 31 | |
Pipelines that prepare documents for search.
IndexingPipeline
Prepares files so they can be searched.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
chunker
|
a BaseChunker. |
required | |
embedder
|
a BaseEmbedder. |
required | |
store
|
a BaseStore. |
required |
Source code in src/rag_titan/pipelines/indexing_pipeline.py
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | |
load_documents(file_paths)
Load every file and skip the ones without any text.
Source code in src/rag_titan/pipelines/indexing_pipeline.py
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | |
run(file_paths, reset=True)
Index the files.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
file_paths
|
list of file paths to index. |
required | |
reset
|
when True, clear the store before adding new chunks. |
True
|
Returns:
| Type | Description |
|---|---|
|
The number of chunks stored. |
Source code in src/rag_titan/pipelines/indexing_pipeline.py
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | |
Tool-calling agents.
BaseAgent
A simple agent that lets an LLM call Python functions.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
llm
|
any BaseLLM that supports tool calling. |
required | |
system_prompt
|
instructions that describe the agent's job. |
required | |
tools
|
list of plain Python functions the LLM may call. |
required | |
max_steps
|
stop after this many think/tool rounds. |
5
|
Source code in src/rag_titan/agents/base_agent.py
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | |
reset()
Forget the conversation and start fresh.
Source code in src/rag_titan/agents/base_agent.py
35 36 37 | |
run(query)
Answer one user message, calling tools as needed.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
query
|
the user's message. |
required |
Returns:
| Type | Description |
|---|---|
|
The agent's final answer text. |
Source code in src/rag_titan/agents/base_agent.py
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | |
MathAgent
Bases: BaseAgent
Agent that uses add, subtract, multiply and divide tools.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
llm
|
a BaseLLM whose model supports tool calling. |
required | |
max_steps
|
stop after this many think/tool rounds. |
5
|
Source code in src/rag_titan/agents/math_agent.py
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | |