DocuStore.io
Architecture

Extraction Pipeline

How DocuStore extracts chemical structures (OCSR), named entities (NER), and summaries from scientific documents.

When a document is uploaded to DocuStore, it enters an automated extraction pipeline that identifies chemical structures, named entities, and generates summaries. Each extraction stage runs as an independent Temporal workflow triggered by domain events.

Chemical Structure Recognition (OCSR)

The compound extraction pipeline uses the structflo-cser ML library to identify chemical structure diagrams in PDF pages and extract their SMILES representations.

How It Works

  1. Trigger -- A Page.Created event fires when a new page is added to an artifact.
  2. Image rendering -- The PDF page is rendered to a high-resolution image (2x zoom via PyMuPDF).
  3. Detection -- A YOLO object detector identifies structure diagram regions and their associated text labels.
  4. Matching -- A neural matcher pairs each structure diagram with its label.
  5. SMILES extraction -- DECIMER converts each detected structure into a SMILES string.
  6. Persistence -- Valid results are stored as CompoundMention value objects on the Page aggregate.
Page.Created → ExtractCompoundMentionsWorkflow
  → YOLO detection → Neural matching → DECIMER SMILES
  → Page.CompoundMentionsUpdated
    → SmilesEmbeddingWorkflow (ChemBERTa indexing)

Each CompoundMention records:

FieldDescription
smilesCanonical SMILES string
extracted_idLabel text from the document (e.g., "SACC-111")
confidenceMatch confidence score
model_nameAlways structflo-cser
date_extractedUTC timestamp

Pairs without a valid SMILES string are silently dropped. The workflow ID compound-extraction-{page_id} ensures idempotency.

Manual Trigger

curl -X POST http://localhost:8000/pages/{page_id}/compounds/extract

Returns 202 Accepted with the workflow ID. Useful for re-running extraction after corrections.

Named Entity Recognition (NER)

The NER pipeline extracts typed entities from page text using structflo-ner, an LLM-powered extraction library tuned for pharmaceutical and biological domains.

Entity Types

TypeExamples
compoundSACC-123, Rifampicin, ethionamide
targetNadD, InhA, KasA
diseasetuberculosis, TB, MDR-TB
geneRv3138, nadD
proteinNaMN adenylyltransferase, EthA
assayMIC, MABA, LORA
bioactivityIC50=2.3uM, MIC90=0.5ug/mL
mechanismcompetitive inhibition, covalent binding
accessionP0A7D9, 3Q5Z, CHEMBL12345

Pipeline Flow

NER runs in parallel with text embedding, both triggered by Page.TextMentionUpdated. They write to different fields on the Page aggregate, so there are no concurrency conflicts.

Page.TextMentionUpdated
  ├─ TextEmbeddingWorkflow (writes text_embedding_metadata)
  └─ NERExtractionWorkflow (writes tag_mentions)
       └─ Page.TagMentionsUpdated
            └─ ArtifactTagAggregationWorkflow

After NER completes for a page, the ArtifactTagAggregationWorkflow collects all tags from all pages of the parent artifact, deduplicates them, and stores the aggregated set on the Artifact. This propagation is eventually consistent -- each new page's NER results refresh the artifact-level tags.

Configuration

VariableDefaultDescription
NER_MAX_CHAR_BUFFER5000Max characters per LLM chunk in NER extraction
GLINER2_MODEL_NAMEfastino/gliner2-large-v1GLiNER2 model for structured metadata extraction

LLM Summarization

Summarization operates at two granularities:

Page Summaries

Each page is summarized individually by an LLM after its text embedding is generated. The sequential dependency (TextMentionUpdated -> embedding -> TextEmbeddingGenerated -> summarization) prevents concurrency conflicts that would occur if both ran in parallel on the same aggregate.

Artifact Summaries

Once all pages in an artifact have summaries, a sliding-window summarization chain produces a document-level summary:

  1. Batch -- Page summaries are grouped into batches of ARTIFACT_SUMMARIZATION_BATCH_SIZE (default 10).
  2. Synthesize -- Each batch is summarized into a batch summary.
  3. Refine -- Batch summaries are iteratively refined into a single coherent document summary.

Prompts for each stage are managed in Langfuse: artifact_batch_summary, artifact_synthesis, artifact_refinement.

Summary Locking

Summaries support a is_locked flag. When a human corrects a summary and locks it, automated re-summarization preserves the locked version. The hil_correction field tracks the human-edited text alongside the original.

Configuration

VariableDefaultDescription
LLM_PROVIDERollamaLLM provider (ollama, openai, gemini)
LLM_MODEL_NAMEgemma3:27bModel for summarization
LLM_TEMPERATURE0.1Low temperature for deterministic summaries
ARTIFACT_SUMMARIZATION_BATCH_SIZE10Pages per batch in artifact summarization