Software Components
Reusable low-level components in the implementation layer
Software components are the core building blocks of the GAIK implementation layer. Each component encapsulates one well-defined capability — speech-to-text, document parsing, structured extraction, classification, or retrieval. They are designed to be used standalone or composed into custom pipelines, giving developers precise control over every step of a knowledge processing workflow.
See also: No-Code Assets for prompt templates and packaged skills.
Use software components when you need fine-grained control over each processing step, when a predefined module doesn't fit your requirements, or when integrating GenAI capabilities into an existing system.
Most chat-based components (Extractor and SchemaGenerator, Classifier, TranscriptEnhancer, AnswerGenerator, Embedder, Postgres and Tabular Agents) accept the same configuration interface for OpenAI, Azure OpenAI, Anthropic, Google, CSC Aitta, other OpenAI-compatible servers, and the optional LiteLLM backend. Available operations depend on the provider and model; see Multi-Provider LLM Client for the gaik.software_components.llm package and the capability matrix.
Transcriber
The Transcriber converts spoken audio or video recordings into written text. It uses OpenAI's Whisper model for accurate speech-to-text transcription and optionally applies a GPT-based post-processing step (the Transcript Enhancer below) to fix transcription errors in the raw output — misspellings, inconsistent terms, and split or merged words — without rewriting it. It handles long recordings automatically through chunked processing, making it suitable for real-world audio captured in noisy or uncontrolled environments.
Key features:
- Whisper-based transcription with high accuracy across languages
- Optional GPT enhancement that repairs ASR errors without rewriting the transcript
- Automatic chunking for recordings of any length
- Supports MP3, WAV, M4A, OGG, and video formats
Potential applications:
-
Workplace incident and safety observation reporting
-
Construction site and field service diaries
-
Meeting and interview transcription
-
Medical dictation and clinical notes
-
Customer call recording analysis
-
Lecture and training material capture
-
Implementation code: software_components/transcriber
-
Usage examples: examples/transcriber
Transcript Enhancer
The Transcript Enhancer improves the quality of raw speech-to-text output through a controlled two-pass LLM workflow — without rewriting or paraphrasing the content. It is designed to reduce the transcription errors that downstream extraction would otherwise inherit. Pass 1 corrects obvious spelling mistakes and normalises repeated terms to a consistent form. Pass 2 uses sentence-level context to repair remaining ASR errors: fixing split or merged compound words, correcting misheard words, and cleaning up minor grammar issues where the correction is unambiguous. The result stays faithful to the spoken content; the goal is error reduction, not prose improvement.
Key features:
- Two-pass workflow: spelling/consistency first, context-based ASR repair second
- Optional correction summary (total changes, insertions, deletions, substitutions)
- Optional diff output showing exactly which spans changed
additional_instructionsparameter to add domain-specific rules (e.g. preserve brand names)- Tuned for Finnish; same structure can be adapted for other languages
Potential applications:
-
Improving transcription quality before structured extraction
-
Construction site diary and safety observation reporting from voice
-
Medical dictation cleanup before clinical data extraction
-
Meeting and interview transcription polishing
-
Any domain where ASR errors would propagate into downstream structured records
-
Implementation code: software_components/enhance_transcript
-
Usage examples: examples/enhance_transcript
Document Parser
The Document Parser converts PDF, DOCX, and other file types into clean, structured markdown text. The package ships eight parser variants so you can match accuracy, cost, and infrastructure needs: vision-based parsing (GPT, Claude, or Gemini), local parsing (PyMuPDF, Docling, and SpreadsheetParser for Excel and CSV files), a Docling + vision hybrid that returns markdown plus metadata, and a remote Docling API client. How much structure survives depends on the variant: the local parsers are the fastest and cheapest route to prose and simple grids, while tables with merged cells or stacked headers need a vision parser, because a markdown pipe table cannot express a merged cell.
Parser variants:
| Parser | When to use |
|---|---|
VisionParser | Shared provider configs with a vision model — OpenAI/Azure, Google/Vertex, Anthropic, Aitta, compatible servers or optional LiteLLM; page images → markdown |
MultimodalParser | Multi-provider PDF → markdown (OpenAI · Anthropic Claude · Google Gemini, or Aitta, compatible servers and LiteLLM via a shared config) with one API |
PyMuPDFParser | Fast local PDF text extraction, no API calls, lowest cost |
DocxParser | Local Word document (.docx) extraction via python-docx |
DoclingParser | Advanced local parsing with OCR, table extraction, multi-format support |
SpreadsheetParser | Local Excel (.xlsx) and CSV to Markdown tables, no API calls. One ## Sheet: <name> table per sheet, with a Row column of source row numbers for citations. .xls is not supported. Install gaik[spreadsheet-parser] |
VisionPlusParser | Docling + vision hybrid that returns markdown and metadata in one pass |
DoclingApiClientParser | Remote client for a hosted Docling parsing service |
Key features:
- Eight parsers covering local, vision, hybrid, and remote-service strategies
- Headings and multi-page structure preserved by the vision and Docling-based parsers (
PyMuPDFParserandDocxParserreturn plain text) - Complex tables preserved by the vision parsers, which can emit HTML
- Multi-page processing with consistent formatting
- Suitable for both simple forms and complex, visually rich documents
Potential applications:
-
Invoice, receipt, and purchase order digitization
-
Contract and legal document preprocessing
-
Technical manual and product specification extraction
-
Research paper and report indexing
-
Compliance document analysis
-
HR form and CV processing
-
Implementation code: software_components/parsers
-
Usage examples: examples/parsers
Extractor
The Extractor turns any unstructured text — transcripts, parsed documents, or free-form notes — into validated, structured records. What makes it distinctive is how extraction is configured: instead of writing code or defining a database schema, you describe what you need in plain language. A Requirement Parser interprets your field definitions, a Schema Generator builds a type-safe Pydantic model, and a Data Extractor uses an LLM to populate each field. The generated schema is saved and reused for future runs, eliminating the cost and latency of regenerating it each time.
Key features:
- Plain-language requirements replace manual schema definition
- Type-safe extraction with full Pydantic validation
- Supports constrained fields, allowed values, and conditional rules
- Schema persistence for efficient batch processing
Potential applications:
-
Incident and safety report field extraction from voice or text
-
Invoice and purchase order data capture
-
Contract clause and obligation extraction
-
Survey and form response structuring
-
Quality inspection data recording
-
HR and recruitment data extraction from CVs
-
Implementation code: software_components/extractor
-
Usage examples: examples/extractor
Vision Extractor
The Vision Extractor turns PDFs and images directly into structured, schema-validated data — without an intermediate Markdown parse step. One LLM call sees all uploaded files together, so the model can use visual layout cues (tables, column alignment, headers, multi-page structure) and reason across documents in a single pass. It is best suited for forms, purchase orders, bills of materials, scanned reports, and any document where parsing quality strongly affects extraction accuracy or where row-level alignment must be preserved across pages or related files.
Key features:
- Single-pass PDF/image → structured data — no parse-then-extract round-trip
- Multi-document calls: align line items in a PO with quantities in a BOM in one request
- Multi-provider: OpenAI / Azure, Anthropic Claude (Foundry), Google Gemini (Vertex AI or direct), plus CSC Aitta, OpenAI-compatible servers or optional LiteLLM through a shared
get_llm_config()config - Reuses generated Pydantic schemas across runs via
schema_dirpersistence - Optional per-field verification: confidence score + reasoning for every scalar field
Potential applications:
-
Purchase order processing with bill-of-materials cross-referencing
-
Invoice and receipt extraction from scanned documents
-
Form digitisation (insurance claims, medical intake, government applications)
-
Layout-sensitive tables (lab reports, financial statements, technical drawings)
-
Human-in-the-loop QA pipelines where each value must be justified
-
Implementation code: software_components/vision_extractor
-
Usage examples: examples/vision_extractor
Document Classifier
The Document Classifier assigns a predefined label to a document based on its content. It uses an LLM to evaluate the document against a user-defined set of classes and returns both the predicted class and a confidence score. It is most useful as a preprocessing step in multi-document pipelines — routing each document to the appropriate extraction schema, storage location, or downstream process before any further processing begins.
Key features:
- Define any set of classes in plain language — no training required
- Returns confidence scores for review and threshold-based routing
- Works as a standalone step or as a gate before extraction
Potential applications:
-
Incoming document triage and routing in finance or legal workflows
-
Email and attachment categorization
-
Insurance claim and case type detection
-
Archive tagging and document library organization
-
Regulatory filing type identification
-
Preprocessing step for multi-schema extraction pipelines
-
Implementation code: software_components/doc_classifier
-
Usage examples: examples/classifier
Jev Classifier
The Jev Classifier assigns one of your classes to a text or a PDF/Word document with Jev, TypeSafe's System One model. Jev returns the chosen label, a probability for every label and a confidence instead of a written answer, so the code around it decides what happens to a doubtful case: mark it "unknown", report a broader label, or send it to a person. It works through the gaik-decide service, so an application needs no TypeSafe key of its own.
Key features:
- Probabilities for every class and a confidence that separates clear cases from doubtful ones
- Confidence gate:
"unknown"or a broader label from a class hierarchy, from one request - Class descriptions passed to the model as the meaning of each option
- Concurrent batch classification where one failed item does not stop the rest
Compared with the Document Classifier: Jev takes text only and gives no written reasoning, but its confidence is calibrated and it is fast and cheap per item. Use the Document Classifier for images, written reasons, or when the text must stay with your own LLM provider. The text sent to Jev leaves CSC for TypeSafe in the United States, so do not send sensitive personal data.
- Implementation code: software_components/jev_classifier
- Usage examples: examples/jev_classifier
Validator (LLM-as-Judge)
The Validator runs a second-pass LLM over the output of an upstream extractor — feeding the source page images plus the extractor's JSON to a vision-capable model and asking it to flag fields whose value doesn't match the document. It returns per-field ok / suspect / wrong flags with reasons and suggested values, plus a token / cost / duration record per call. Useful when missing or hallucinated fields are expensive downstream and you want a cross-provider sanity check before acting on extraction output.
Key features:
- Same code talks to OpenAI / Azure OpenAI / Anthropic Foundry / Google Vertex via the toolkit's existing config helpers, or to CSC Aitta, OpenAI-compatible servers and optional LiteLLM via
LLMJudge(config=get_llm_config(...)) - Returns per-field flags (
ok,suspect,wrong) plus a document-level slot for structural observations like "items missing from the extractor output" - Domain-agnostic by default; pass an optional
ValidationRubricwith vendor-specific check sentences when you want targeted guidance - Cost tracking with longest-prefix model lookup so rotated model ids still resolve to a known rate
- Text-vs-text mode (
judge.judge_text_pair(extracted, expected, field_name=...)) compares two short strings for semantic equivalence without any source document — useful for scoring audio-transcription extractors against hand-annotated ground truth where exact-string match misses paraphrasing - Schema-agnostic hallucination detector (
judge.detect_hallucinations(source_text, extracted)) inspects an extractor's JSON as a whole against a source document and returns oneHallucinationFlagper problem field — drop-in replacement for hand-written keyword post-validators that only cover a single schema
Potential applications:
- Purchase-order extraction QA before sending the order downstream
- Invoice / receipt extraction sanity check
- Form-extraction review where missing or hallucinated fields are expensive
- Two-tier setups: cheap pre-screen + premium judge on flagged rows
Recommended judge model: gemini-3-flash-preview via Vertex AI — F1 = 1.000 at $0.004/PO in our internal Luvata judge benchmark across 8 candidates including GPT-5.4 / 5.5, Claude Haiku 4.5 / Sonnet 4.6 / Opus 4.7, and Gemini 3.1 Flash Lite.
- Implementation code: software_components/validators/llm_judge
- Usage examples: examples/validators
Text-to-Speech
The Text-to-Speech component converts written text into spoken audio using OpenAI or Azure OpenAI TTS models. It accepts plain text and returns an audio file in a configurable format, with control over voice, language, speed, and output format. It is useful anywhere a workflow needs to deliver information aurally — generating audio versions of extracted content, reading back structured report summaries, or producing narration for instructional content.
Key features:
- Supports OpenAI and Azure OpenAI TTS backends with the same interface
- Configurable voice, language (Finnish and English), speed, and audio format
- Returns a
SpeechSynthesisResultwith audio bytes, model, and metadata - Simple
result.save("output_dir")for persisting audio to disk
Potential applications:
-
Audio delivery of extracted report summaries for field workers
-
Accessibility features for reading back structured content aloud
-
Voice notifications in automated workflow pipelines
-
Generating narration for training or instructional content
-
Implementation code: software_components/text_to_speech
-
Usage examples: examples/text_to_speech
RAG Components
The RAG (Retrieval-Augmented Generation) components provide a modular pipeline for building document-grounded question answering systems. Rather than a single monolithic tool, the RAG pipeline is split into six composable blocks — each with a clear responsibility. You can use individual blocks where needed or assemble the full pipeline for a complete Q&A system grounded in your own documents.
Pipeline overview:
1 · RAG Parser
Extracts text from source documents and splits it into manageable chunks with preserved metadata (page number, source file, section heading). The chunks serve as the unit of indexing and retrieval throughout the rest of the pipeline.
Example: A company safety manual (150 pages) is parsed into ~600 chunks. Each chunk carries its page number and section title so answers can be traced back to the source.
2 · Embedder
Converts each text chunk into a dense numerical vector using an embedding model. Semantically similar chunks produce similar vectors, enabling meaning-based search rather than keyword matching.
Example: The chunk "All incidents must be reported within 24 hours of occurrence" is embedded as a vector. A question like "What is the deadline for incident reporting?" produces a similar vector — enabling a match even though no keywords are shared.
3 · Vector Store
Stores and indexes all embeddings for fast similarity search at query time. The vector store persists the knowledge base between sessions, so documents only need to be processed once and can be queried repeatedly.
Example: A product documentation knowledge base is indexed once and reused across hundreds of daily queries without reprocessing the source documents.
Two backends are available: in-memory / ChromaDB for quick prototyping, and PostgreSQL + pgvector (PgVectorStore) for production use with semantic, keyword, and hybrid search (RRF). See Hybrid Search (PostgreSQL) below.
4 · Retriever
Accepts a user question, embeds it, and searches the vector store for the most semantically relevant chunks. Optionally reranks results to improve precision before passing them to the answer generator.
Example: The question "What PPE is required in the assembly area?" retrieves the three most relevant policy chunks from a 200-page safety manual, even if the manual never uses the exact word "PPE".
5 · Ranker
Takes the ranked lists a search step produced and decides the final order. It can fuse several rankings into one, rescore candidates with a cross-encoder, or reorder by a business field such as a date or a price. It performs no search of its own — it reorders results you already have.
Fusion works on ranks, not raw scores. A semantic score and a keyword score sit on incompatible scales, so combining them arithmetically lets one signal dominate for reasons unrelated to relevance. Reciprocal Rank Fusion sidesteps this, and extends naturally to non-search signals like recency.
Each result carries the rank it held in every contributing signal, so it is possible to see why a document ended up where it did — and a document missing from one signal is visibly missing rather than silently scored zero.
Example: A product search fuses semantic relevance with keyword matching, weighted 70/30, then lets the user re-sort the same result set by price ascending without running the search again.
6 · Answer Generator
Takes the retrieved chunks and the original question and uses an LLM to compose a coherent, factual answer. The response is grounded strictly in the retrieved content, and source citations are included so the answer can be verified.
Example: Given the retrieved policy chunks, the answer generator responds: "According to the Safety Manual (Section 4.2), employees in the assembly area must wear safety glasses, steel-toed boots, and high-visibility vests at all times."
Key features:
- Fully modular — use individual blocks or assemble the full pipeline
- Metadata-preserving chunking for accurate source attribution
- Rank fusion across semantic, keyword and business signals, with per-signal provenance
- Optional reranking to improve retrieval precision
- Re-sortable results — order by relevance or by any metadata field, ascending or descending
- Citation-aware answer generation for trustworthy, verifiable outputs
Potential applications:
-
Internal knowledge base and company policy Q&A
-
Technical documentation and product manual assistants
-
Regulatory and compliance document lookup
-
Customer support knowledge retrieval
-
Contract and legal clause search
-
Training material and onboarding knowledge assistants
-
Implementation code: software_components/RAG
-
Usage examples: examples/RAG
Hybrid Search (PostgreSQL)
Hybrid search answers a query with two searches over one PostgreSQL table and merges the results. The vector arm finds passages that answer in other words; the keyword arm finds exact tokens an embedding blurs, such as a form number or a section reference. PgVectorStore holds the documents, their embeddings and a full-text index in the same table, so there is no second system to keep in step, and it offers semantic, keyword and hybrid search behind one interface. For Finnish text the keyword arm can use Postgres' own stemmer or, through the FinnishTextProcessor, dictionary forms on both the indexing and the query side.
Example: An HR handbook is indexed once. "When do I get my holiday pay?" is answered by the vector arm, which matches the meaning; a search for "ML-204" is answered by the keyword arm, which returns the one passage that names that form.
Key features:
- Three modes over the same data —
hybrid,vectorandkeyword— so each arm's contribution can be compared - One
setup()call creates the table, the HNSW and full-text indexes and the SQL functions; it is safe to run again - JSONB metadata filters on every mode
- Each hybrid result reports its rank in both arms, so an arm that contributes nothing is visible per result
- Finnish support at two levels: Postgres' built-in stemmer, or lemmatization on both sides with a pinned backend
RelevanceGatecalibrates a similarity floor from your own queries, to tell "nothing relevant" apart from a weak match
Potential applications:
-
Document and policy search where users type both questions and exact codes
-
The retrieval step of a RAG assistant that must say when the library has no answer
-
Search over Finnish-language material
-
Transcript and video-segment search with metadata filters
-
Setup guide: Hybrid Search on PostgreSQL
-
Implementation code: RAG/pg_vector_store
-
Usage example: hybrid_search_example.py
Postgres Agent
The Postgres Agent is a text-to-SQL query agent: connect it to a PostgreSQL database, ask a question in plain language, and get an answer backed by a validated, read-only SQL query. It introspects the schema, asks an LLM for a query, validates it, runs it, and — if the query fails — feeds the error back to the LLM and retries in a lightweight agentic loop. It is read-only by design: only SELECT / WITH ... SELECT queries are allowed, statements are parsed and rejected if they touch other schemas or attempt writes, and the real guarantee comes from connecting with a read-only database role.
Key features:
- Natural language → validated, read-only SQL → natural-language answer in one
ask()call - Agentic retry loop: SQL errors (including statement timeouts) are fed back to the LLM for correction
- Defense in depth:
sqlglotvalidation rejecting non-SELECT, multi-statement, DDL/DML, and cross-schema queries, plus a read-only transaction,statement_timeout, and row cap — backed by a read-only DB role table_allowlistnarrows the agent to specific tables; queries touching anything else are rejected before runningextra_instructionsinjects a domain glossary or example question→SQL pairs;answer_languagelocalises the answer (en, fi, sv, de, fr, es, no, da)- Multi-provider LLM (OpenAI / Azure / Anthropic / Google / CSC Aitta / OpenAI-compatible servers / optional LiteLLM, via
get_llm_config());get_schema()andrun_sql()work without LLM credentials, so they double as tools for an external agent framework
Potential applications:
-
Self-service analytics — let non-technical staff query a database in plain language
-
Conversational dashboards and reporting over operational data
-
Ad-hoc data exploration without writing SQL by hand
-
A safe, read-only query tool inside a larger agent or chatbot
-
Implementation code: software_components/postgres_agent
-
Usage examples: examples/postgres_agent
Tabular Agent
The Tabular Agent is the file-shaped sibling of the Postgres Agent: upload a CSV or Excel file, ask a question in plain language, and get an answer backed by a validated, read-only SQL query. It loads your files into an in-memory DuckDB database, profiles every column, asks an LLM for a query, validates it, runs it, and — if the query fails — feeds the error back and retries. Real spreadsheets are rarely tidy, so report-style sheets with title rows, blank spacers, interleaved subtotals and trailing note blocks are cleaned up before anything is queried: the header row and subtotal rows are found deterministically at no token cost, and only sheets that still look messy trigger a single extra LLM call to locate the real table.
Key features:
- Ask your own CSV, Excel, Parquet or JSON files questions — no database required
- Messy-spreadsheet clean-up: title rows, blank spacers, subtotals and note blocks are removed; a subtotal is recognised by structure rather than by the word "total", so it works in any language
- Nordic number formats (
1 234,56) become real numbers, soSUM()works on Finnish and Swedish exports - Column profiling puts each column's type, null share, range and actual values in the prompt — the single biggest accuracy lever, and it costs no tokens
- Each Excel sheet becomes its own table, so a question can join across sheets
- Two security layers:
sqlglotvalidation that rejects file-reading table functions and any unrecognised function (an allowlist, not a denylist), plus a DuckDB connection locked withenable_external_access = falsebefore a single generated query runs - Multi-provider LLM (OpenAI / Azure / Anthropic / Google / CSC Aitta / OpenAI-compatible servers / optional LiteLLM, via
get_llm_config());get_schema()andrun_sql()work without LLM credentials, so they double as tools for an external agent framework
Potential applications:
-
Self-service analytics over spreadsheets people already email around
-
Answering questions about an uploaded file in a chatbot or support tool
-
Ad-hoc exploration of survey results, exports and finance reports without writing SQL
-
Turning a monthly report workbook into something queryable
-
Implementation code: software_components/tabular_agent
-
Usage examples: examples/tabular_agent
Source Normalizer
The Source Normalizer converts a mixed set of files, such as a project folder, into Markdown texts that keep their provenance. PDFs, Word files and spreadsheets are parsed locally and text files are read as they are. Recordings go to the Transcriber and images to the VisionParser. Each text records its file name, the group it was given in (such as primary or secondary), its file type and the tool that produced it. It is the first stage of the Report-Writer module, and it is also useful on its own: one call turns mixed files into a set of Markdown texts, for example for RAG ingestion or for the Extractor.
Key features:
- One call for mixed files:
SourceNormalizer(config).normalize({"primary": [...], "secondary": [...]}), or a plain list of paths. The config is needed only for recordings and images - Provenance for every text:
file,source_class,source_typeandtool - Citation-ready text: each PDF page starts with a
[Page N]line, Word headings become#headings, and spreadsheet tables carry the source row numbers - Recordings give the raw transcript, which has no per-utterance timestamps
- Fails loudly: an unsupported type (such as
.pptx,.docor.xls), a missing file, two files with the same name, a PDF with no text layer or a file that yields no text raises instead of being skipped. All paths are checked before the first conversion save()writes one Markdown file per source and asources.jsonmanifest, andNormalizedSources.load()reads them back, so the texts can be edited before use- Options:
vision_model,transcription_modelandlanguage - Install:
pip install "gaik[source-normalizer]". Recordings need OpenAI or Azure OpenAI
Potential applications:
-
Preparing mixed document folders for RAG ingestion
-
Turning site recordings, notes and documents into text for the Extractor or other LLM steps
-
The ingestion step of source-grounded report writing
-
Implementation code: software_components/source_normalizer
-
Usage examples: examples/source_normalizer
Knowledge Curator
The Knowledge Curator collects the evidence for a fixed set of topics from normalized sources. For each topic, called a section, an LLM extracts fact units: a short summary paired with the exact words of the source, the file it came from and a locator such as a page or a sheet row. It also lists the required items that no source covers and the conflicts between sources. The source hierarchy in the instructions decides whether a conflict is resolved or unresolved. Every quote is checked against its source. It is the second stage of the Report-Writer module. On its own it suits any task that needs traceable evidence for fixed questions, such as audits and due diligence.
Key features:
KnowledgeCurator(config, model=None, *, max_workers=4, chat_options=None, drop_unverified=True)andcurate(sources, sections, *, instructions=""): one structured-output call per section, run in parallel- Sections are
SectionSpecobjects with an id, a title, instructions and required items. Sections withdepends_onare derived and are not curated - Verified quotes: a quote must occur in its cited source, and only whitespace may differ. A failing section is requested again once with the failing quotes as feedback; if a quote still fails, that fact is dropped, the rest of the section is kept and the dropped facts are listed in
KnowledgeBase.dropped. Withdrop_unverified=False,curate()raisesValueErrorinstead - Locators:
page Nfor PDFs,sheet <name>, row <n>for spreadsheets, the nearest heading for other structured documents, and null for recordings and plain text - Editable output:
save()writes one JSON file per section.KnowledgeBase.load()validates edited files andverify_quotes(sources)checks the quotes again - Texts that already exist can be wrapped with
NormalizedSources.from_texts(...), so the Source Normalizer is optional - Install:
pip install "gaik[knowledge-curator]"(core dependencies only). Works with any provider supported byget_llm_config - The curator's calls are not counted in any token usage total
Potential applications:
-
Audit evidence collection, with a quote and a location for every finding
-
Technical and legal due diligence
-
Gap checks: which required items no source covers
-
Finding conflicting statements across a document set
-
The knowledge input of the Report Synthesizer
-
Implementation code: software_components/knowledge_curator
-
Usage examples: examples/knowledge_curator
Draft Reviewer
The Draft Reviewer fact-checks generated text against reference material. It works on any text: summaries, report sections, incident reports or meeting minutes. An LLM proposes exact search-and-replace edits, each with a reason. An edit is applied only where its search text occurs exactly once, and failed edits go back to the model for new ones. The result is the corrected text with a log of the applied edits and the edits that could not be applied. The Report Synthesizer uses it to review every section, but it can check the output of any generation step against its source.
Key features:
DraftReviewer(config, model=None, *, max_attempts=5)andreview(draft, *, reference, instructions=""), which returns aReviewResultwithtext,appliedandunresolved- Default checks: every factual claim must be supported by the reference, wrong numbers, dates, names and attributions are corrected, unsupported claims are removed, and style and order are left alone.
instructionsreplaces these checks - Exact matching: no fuzzy or case-insensitive matching. An empty
replacedeletes the passage - Bounded retries: at most
max_attemptsrequests, the first one included. Edits that still fail are returned inunresolved, not raised, so the caller decides whether they are fatal - An empty draft or reference raises
ValueError - Install:
pip install "gaik[draft-reviewer]"(core dependencies only). Works with any provider supported byget_llm_config - The reviewer's calls are not counted in any token usage total
Potential applications:
-
Checking an LLM summary against the source document
-
Checking a generated incident report against its transcript
-
Checking meeting minutes against the meeting notes
-
A review step after any generation component, with a log of each correction
-
Implementation code: software_components/draft_reviewer
-
Usage examples: examples/draft_reviewer
Report Synthesizer
The Report Synthesizer writes a governed report section by section from curated knowledge. Each technical section is written from its own knowledge only. Derived sections, such as recommendations and a summary, are written afterwards from the reviewed texts of the sections they depend on. A Draft Reviewer with its own model setting checks every draft, and a review log records the edits. The knowledge is plain data: it usually comes from the Knowledge Curator, but it can also be written by hand. It is the third stage of the Report-Writer module.
Key features:
ReportSynthesizer(config, model=None, *, reviewer_model=None, strict_review=False, review_attempts=5, writer_options=None, reviewer_options=None, citations=True)andsynthesize(knowledge, sections, *, title, language="English", instructions="", sample_report=None), which returns aReport- LangGraph workflow: sections without dependencies start in parallel, and a derived section starts once its prerequisites are reviewed
- The writer uses only the facts in its material, writes
(missing: <item>)for each required item the material does not cover, and states both sides of an unresolved conflict, markedUnresolved: sample_reportsets structure, length and tone only. It contributes no content and never goes to the reviewer- Before any LLM call,
synthesize()raisesValueErrorfor duplicate section ids, an unknown dependency, a dependency cycle, or knowledge that does not match the non-derived sections citations=Falsewrites the facts without source citations: the writers give no file names or locators and the reviewer removes any that remainstrict_review=Truestops the run when a reviewer edit cannot be appliedreport.save(directory)writessections/NN_<id>.md,review_log.json,report.mdandreport.docx. Hand-edited section files are loaded withReport.load()and saved again, which rebuilds the report without a model callreport.usagecounts the writer and reviewer calls- Install:
pip install "gaik[report-synthesizer]", which adds LangGraph andpypandoc. DOCX export also needs the Pandoc binary;save(..., docx=False)skips it
Potential applications:
-
Condition assessments and inspection reports from verified findings
-
Audit and due diligence reports from collected evidence
-
Recurring reports from facts that a team keeps by hand
-
The writing stage of source-grounded report pipelines
-
Implementation code: software_components/report_synthesizer
-
Usage examples: examples/report_synthesizer
GAIK