No description
  • Python 99.1%
  • Makefile 0.9%
Find a file
2026-06-21 21:49:59 +02:00
.vscode Adjusted vscode settings 2026-06-21 21:49:59 +02:00
configs Harden admin flow and add offline evaluation 2026-06-21 02:24:12 +02:00
demo Harden admin flow and add offline evaluation 2026-06-21 02:24:12 +02:00
docs Remove old report documents 2026-06-21 11:21:48 +02:00
examples Add hot-folder connector and local runtime layout 2026-06-19 15:00:12 +02:00
external Initial commit 2026-06-15 23:37:52 +02:00
local_models Track RAG model downloader 2026-06-20 16:25:32 +02:00
src Deleted temporary and empty directories 2026-06-21 11:10:04 +02:00
test_documents Curate test corpus and harden tool workflows 2026-06-20 20:45:51 +02:00
tests Harden admin flow and add offline evaluation 2026-06-21 02:24:12 +02:00
.gitignore Deleted temporary and empty directories 2026-06-21 11:10:04 +02:00
.markdownlint.yml Added markdownlint 2026-06-20 00:30:41 +02:00
environment.lock.yml Add standalone admin_rag retrieval MVP 2026-06-20 16:23:42 +02:00
environment.yml Track RAG model downloader 2026-06-20 16:25:32 +02:00
Makefile Harden admin flow and add offline evaluation 2026-06-21 02:24:12 +02:00
pyproject.toml Adjusted pyproject.toml for PyTest 2026-06-21 13:26:14 +02:00
pyrightconfig.json Initial commit 2026-06-15 23:37:52 +02:00
README.md Remove old report documents 2026-06-21 11:21:48 +02:00

Administration Copilot

Administration Copilot is a local-first Python workspace for building modular AI-assisted administrative workflows. The long-term system is meant to ingest incoming work items such as e-mails, PDFs, scans, uploads, or API payloads, classify and route them, extract structured business data where needed, retrieve missing context, and create review-only outputs for human approval.

The project is intentionally split into small modules instead of one large assistant package. The current implemented MVP focuses on three review-only workflows: e-mail reply drafting, action-only task extraction, and offer/quote extraction from PDFs or scans. It also includes a standalone RAG retrieval module for local context lookup experiments. The workflow modules use shared model/tool infrastructure, SQLModel-based inbox persistence, LangGraph checkpointing, and a synthetic test-document corpus.

The official local MVP entry point is now admin-flow: a headless orchestration CLI that runs one source file through ingestion, normalization, routing, optional reviewed route fallback, explicit/safe acceptance, downstream execution, persistence, and a chronological result payload.

Current State

Implemented today:

  • admin_mail: LangGraph-orchestrated e-mail reply drafting with native tool-calling, optional RAG-backed context retrieval, deterministic review guards, and SQLite checkpoints.
  • admin_tasks: LangGraph-orchestrated extraction of review-only tasks from already routed e-mails that should not receive a direct reply.
  • admin_inbox: SQLModel persistence for incoming items, their body, document, and attachment parts, e-mails, review-only drafts/tasks, and lightweight normalization of stored .eml/text files.
  • admin_common: shared tool contracts, OpenAI-compatible adapters, local llama.cpp client, and LangGraph SQLite checkpointing.
  • admin_connectors: source connectors, currently a local hot-folder connector that ingests stable files into admin_inbox.
  • admin_route: deterministic first-hop routing for normalized incoming items into mail reply, task extraction, document processing, human review, or no action, with persisted reviewable route decisions and optional reviewed LLM fallback for otherwise uncertain text items.
  • admin_flow: official headless MVP orchestration across connector, inbox, routing, optional fallback, accepted route execution, and result summary.
  • admin_eval: offline evaluation helpers, currently focused on measuring deterministic routing against the synthetic fixture metadata.
  • admin_idp: LangGraph-orchestrated offer/quote extraction from PDFs or images, using pymupdf4llm for PDF text and EasyOCR as CPU-only OCR fallback.
  • admin_rag: standalone Chroma/E5 retrieval over synthetic context fixtures, with opt-in context-provider integration for mail and task workflows.
  • test_documents: neutral synthetic .eml and PDF fixtures with separate metadata labels for future routing, IDP, RAG, and mail tests.

Prepared but not implemented yet:

  • GraphRAG, reranking, and RAG-backed context for document extraction.
  • Real mailbox/API connectors, mailbox sync, sending e-mail, and human review UI.
  • A standalone Streamlit portfolio demo lives under demo/. It visualizes the current PDF/IDP flow, but it is not a production review UI.

All generated e-mail replies are drafts only. No module sends e-mail.

Module Layout

src/
|-- admin_common/   # shared contracts, adapters, orchestration, model clients
|-- admin_connectors/ # local source connectors such as hot-folder ingestion
|-- admin_inbox/    # incoming-item boundary; e-mail, draft, and task persistence
|-- admin_idp/      # review-only document processing and quote extraction
|-- admin_mail/     # review-only e-mail reply drafting
|-- admin_rag/      # standalone Chroma/E5 retrieval and optional context source
|-- admin_tasks/    # review-only action/task extraction from e-mails
|-- admin_route/    # deterministic first-hop routing for normalized items
|-- admin_flow/     # official headless MVP orchestration over the modules
`-- admin_eval/     # offline quality checks over fixture metadata

Future GraphRAG, reranking, and document-processing RAG are described in docs but are not implemented yet.

The package names follow the module boundaries: admin-mail for reply drafts and admin-tasks for action-only task extraction. The repository-level product vision is broader: Administration Copilot.

Environment

Create the Conda environment:

conda env create -f environment.yml
/home/archuser/miniconda3/envs/admin-ai/bin/python -m pip install -e ".[dev,rag]"

If admin-ai already exists:

conda env update -n admin-ai -f environment.yml --prune
/home/archuser/miniconda3/envs/admin-ai/bin/python -m pip install -e ".[dev,rag]"

The local admin-ai environment installs EasyOCR with CPU-only PyTorch wheels for OCR fallback. If you install outside Conda and want OCR support, use the ocr extra with a CPU-only PyTorch setup.

The Makefile and VSCode workspace default to the admin-ai Python executable directly. Activating the Conda environment is still convenient for interactive shell work, but it is not required for make targets.

Checks

make ci
make markdownlint

This runs Ruff, Mypy, focused Pyright checks, and Pytest over the current first-party code, demo code, examples, and test corpus helpers. The Makefile uses the project's admin-ai Python by default; portable users can override it with PYTHON=/path/to/python make ci. make markdownlint checks the repository documentation with the shared Markdownlint configuration.

Local Runtime

Local runtime artifacts are grouped under one ignored directory:

local_runtime/
|-- inbox.sqlite
|-- langgraph_checkpoints.sqlite
|-- flow_checkpoints.sqlite
|-- demo/
|-- flow_runs/
|-- idp_parts/
|-- rag/
|-- incoming/
|-- processing/
|-- processed/
`-- failed/

inbox.sqlite stores business state from admin_inbox. langgraph_checkpoints.sqlite stores technical LangGraph run state. flow_checkpoints.sqlite stores technical state for the outer admin-flow orchestration graph. demo/ stores disposable Streamlit portfolio-demo runtime state. flow_runs/ stores isolated per-run hot-folder folders created by admin-flow. idp_parts/ stores extracted document attachments from .eml files when a routed e-mail needs document processing. rag/chroma/ stores disposable local Chroma indexes for admin_rag. incoming/ stores local source files used by connectors.

The connector layer stores raw source files first. admin_inbox can then normalize stored .eml and plain-text items into a small structured shape for future routing. A normalized item can contain parts: for example an e-mail body plus PDF attachments. PDFs and images can now be routed to admin_idp for review-only offer/quote extraction.

The low-level route dispatcher connects the pieces without executing downstream workflows automatically:

StoredIncomingItem
-> normalize_incoming_item(...)
-> route_normalized_item(...)
-> StoredRouteDecision
-> incoming item marked routed
-> explicit accept/override
-> explicit execute for mail/task/document routes

Route decisions are reviewable business records. A mail_reply, task_extraction, or document_processing route starts the LLM workflow only after the decision is accepted or overridden and then executed explicitly through admin-route execute. human_review and no_action remain parked.

For the MVP, prefer the higher-level admin-flow run command. It performs the same steps as one reproducible run and can optionally auto-accept safe, non-safety routes for local demos and smoke tests.

Hot-Folder Connector

Create an empty local hot-folder layout:

admin-connectors hot-folder init

This creates:

local_runtime/
|-- incoming/
|-- processing/
|-- processed/
`-- failed/

local_runtime/ is ignored by Git. Put test files directly into local_runtime/incoming/, then scan once into local_runtime/inbox.sqlite:

admin-connectors hot-folder scan --stable-after-s 0

Limit ingestion to selected extensions when needed:

admin-connectors hot-folder scan --allow-extension .eml --allow-extension .pdf

The connector detects duplicate files by SHA-256. Duplicates are archived under processed/ but are not stored as new inbox items. The inbox database enforces that digest as unique for incoming items. If ingestion fails after a file has already moved through processing/, the latest known file path is moved to failed/ instead of leaving a stranded file behind.

For a simple polling watcher while the program is running:

admin-connectors hot-folder watch --interval-s 5

Documentation

CLI And Examples

The installed CLIs expose connector, routing, reply, and task workflows:

admin-mail --help
admin-mail reply-draft --help
admin-mail tool-contracts
admin-tasks --help
admin-tasks extract --help
admin-idp --help
admin-idp extract --help
admin-rag --help
admin-rag index --help
admin-rag query --help
admin-connectors --help
admin-connectors hot-folder --help
admin-route --help
admin-flow --help
admin-flow run --help
admin-eval --help
admin-eval routing --help

Official headless MVP sequence:

admin-rag index test_documents/rag_seed --reset --json
admin-flow run test_documents/documents/item_000019.eml \
  --language de \
  --use-rag-context \
  --use-llm-route-fallback \
  --auto-accept safe \
  --json

This command ingests the source file through an isolated local hot-folder run, stores it in admin_inbox, normalizes it, routes it, optionally uses the reviewed route fallback only for uncertain text, accepts safe executable routes, and then executes the accepted mail/task/document workflow.

For repeatable local runs, the same settings can be put into a TOML config and overridden per command:

admin-flow run test_documents/documents/item_000019.eml \
  --config configs/admin-flow.local.example.toml \
  --auto-accept safe \
  --use-rag-context \
  --json

Two more example configs are available:

  • configs/admin-flow.fast-dev.example.toml: faster local smoke settings.
  • configs/admin-flow.full-local.example.toml: fuller local run with RAG and reviewed route fallback enabled.

admin-flow returns structured failure payloads with the failed node, code, message, error type, and details. The llama.cpp client also supports retrying transient HTTP failures for real HTTP calls; fake transports used in tests still fail immediately.

The main execution levels are:

Level Use Notes
admin-flow Official local MVP entry point Ingests, routes, accepts safely, executes, and persists.
admin-route Manual route debugging Lets you route, accept, override, and execute step by step.
admin-mail, admin-tasks, admin-idp Focused module runs Useful when one module should be tested directly.
admin-rag Standalone retrieval Index and query context data independently.
Internal workflow helpers Tests/debugging Kept for fake transports and narrow unit tests.

Review-capable JSON payloads include a compact review_summary so failed review guards can be spotted without reading the raw tool-message payload.

Offline routing evaluation is available without starting llama.cpp:

admin-eval routing --json

This compares deterministic routing against test_documents/metadata and prints aggregate accuracy plus mismatches. Treat this as a quality signal, not as a guarantee that the router is finished.

Low-level routing sequence for debugging or manual stepping:

admin-connectors hot-folder scan --stable-after-s 0 --json
admin-route route <incoming_item_id> --json
admin-route accept <decision_id> --json
admin-route execute <decision_id> \
  --language de \
  --context-note "Use trusted local context for this review-only draft." \
  --json

Examples:

python examples/run_email_reply_workflow.py --show-raw-tool-arguments
python examples/run_email_tasks_workflow.py --show-raw-tool-arguments
python examples/run_tool_contracts.py

These scripts are still useful for learning and inspecting native tool calls in one module at a time. They are not the official source-to-result MVP path; use admin-flow run for that.

Run a direct document extraction smoke against a local llama.cpp server:

admin-idp extract test_documents/documents/item_000028.pdf \
  --document-type quote \
  --language de \
  --json

Build and query the standalone RAG seed index:

admin-rag index test_documents/rag_seed \
  --db-dir local_runtime/rag/chroma \
  --reset \
  --json

admin-rag query "Montagefenster Nordtor Bauleiter" \
  --db-dir local_runtime/rag/chroma \
  --top-k 5 \
  --json

Use the same index as trusted context for an accepted mail or task route:

admin-route execute <decision_id> \
  --language de \
  --use-rag-context \
  --rag-db-dir local_runtime/rag/chroma \
  --json

Routing remains deterministic by default. The optional LLM route fallback is available only for uncertain, non-safety text items and is reviewed by a local tool before it can create a replacement decision. RAG is used only after a route decision has been accepted and only as the get_context provider for mail replies or task extraction.

The e-mail bodies and local example context used by the workflow examples live together under examples/data/:

reply_request_de.txt
reply_context_de.txt
task_request_de.txt
task_context_de.txt

The real local smoke path is llama.cpp + native tool-calling + LangGraph + SQLite checkpointing. By default, make serve uses the local Qwen3 dev model:

make serve
admin-flow run test_documents/documents/item_000019.eml \
  --use-rag-context \
  --use-llm-route-fallback \
  --auto-accept safe \
  --json
python examples/run_email_reply_workflow.py --show-raw-tool-arguments
python examples/run_email_tasks_workflow.py --show-raw-tool-arguments
admin-idp extract test_documents/documents/item_000028.pdf --document-type quote --json

MODEL_PATH is still overrideable for model comparisons:

make serve MODEL_PATH=local_models/Qwen3-4B-Instruct-2507-Q5_K_M.gguf
make serve MODEL_PATH=local_models/Meta-Llama-3.1-8B-Instruct-Q8_0.gguf
make serve MODEL_PATH=local_models/LFM2.5-8B-A1B-Q8_0.gguf

Test Document Corpus

Curated synthetic fixtures live under:

test_documents/
|-- documents/  # neutral source files such as item_000001.eml
|-- metadata/   # labels, expected routes, thread links, safety flags
`-- rag_seed/   # retrieval context for standalone admin_rag tests

Source filenames and attachment names are intentionally neutral to avoid data leakage. Semantic labels belong in metadata only. The corpus is curated in place; do not regenerate it from a script.