Metadata-Version: 2.4
Name: iil-fieldprefill
Version: 0.2.0
Summary: AI field enrichment — shared prefill orchestration for Django platform apps
Author-email: Achim Dehnert <achim@dehnert.com>
License: MIT
Keywords: ai,aifw,django,field-enrichment,llm,prefill
Classifier: Development Status :: 3 - Alpha
Classifier: Framework :: Django :: 5.0
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.11
Requires-Dist: iil-aifw>=0.9.0
Requires-Dist: pydantic>=2.0
Provides-Extra: all
Requires-Dist: asgiref>=3.7; extra == 'all'
Requires-Dist: django>=4.2; extra == 'all'
Requires-Dist: iil-promptfw>=0.5.0; extra == 'all'
Provides-Extra: dev
Requires-Dist: hatch; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: ruff; extra == 'dev'
Provides-Extra: django
Requires-Dist: asgiref>=3.7; extra == 'django'
Requires-Dist: django>=4.2; extra == 'django'
Provides-Extra: promptfw
Requires-Dist: iil-promptfw>=0.5.0; extra == 'promptfw'
Description-Content-Type: text/markdown

# iil-fieldprefill

AI field enrichment — shared prefill orchestration for Django platform apps.

**ADR-107:** Use `iil-fieldprefill` as shared AI field enrichment layer.

## Installation

```bash
pip install iil-fieldprefill                    # Core only
pip install 'iil-fieldprefill[django]'          # With Django HTMX mixin
pip install 'iil-fieldprefill[promptfw]'        # With promptfw templates
pip install 'iil-fieldprefill[all]'             # Everything
```

## Quick Start

```python
from fieldprefill import prefill_field, PrefillResult

result: PrefillResult = prefill_field(
    field_key="geltungsbereich",
    prompt="Beschreibe den Geltungsbereich...",
    action_code="ex_doc_prefill",
    max_tokens=2048,
)
print(result.content)        # Generated text
print(result.tokens_used)    # Input + output tokens
print(result.model)          # e.g. "gpt-4o"
print(result.latency_ms)     # Call duration
```

## Multi-Field Prefill (v0.2.0+)

Enrich multiple fields in a single LLM call with structured JSON response:

```python
from fieldprefill import prefill_fields

result = prefill_fields(
    field_keys=["description", "emotional_arc"],
    prompt="Enrich this chapter with a detailed description and emotional arc.",
    action_code="outline_enrich",
    context={"title": "Chapter 1", "act": "Act I", "beat_phase": "Inciting Incident"},
    scope="writing.outline_enrichment",
)

# Access individual fields from JSON response
node.description = result.get("description")
node.emotional_arc = result.get("emotional_arc")

# Or get full dict
data = result.as_dict()  # {"description": "...", "emotional_arc": "..."}
```

## Cross-Hub Usage

### risk-hub — Hazard field enrichment

```python
# Register retrievers in AppConfig.ready()
from fieldprefill.retrievers import register_retriever

@register_retriever("sds")
def get_sds_texts(tenant_id, instance=None):
    from substances.models import Substance
    return [s.summary for s in Substance.objects.filter(tenant_id=tenant_id)]

# Prefill a field using existing document context
result = prefill_field(
    field_key="schutzmassnahmen",
    prompt="Beschreibe die erforderlichen Schutzmaßnahmen...",
    action_code="ex_doc_prefill",
    sources=["sds", "gefaehrdungsbeurteilung"],
    scope="explosionsschutz.ex_doc",
    tenant_id=request.tenant_id,
)
```

### writing-hub — Outline node enrichment

```python
@register_retriever("project_context")
def get_project_context(owner_id, instance=None):
    from apps.authoring.services.project_context_service import ProjectContextService
    ctx = ProjectContextService().get_context(str(instance.pk))
    return [ctx.to_prompt_block()]

result = prefill_fields(
    field_keys=["description", "emotional_arc"],
    prompt="Verfeinere dieses Kapitel mit detaillierter Beschreibung und emotionalem Bogen.",
    action_code="chapter_outline",
    sources=["project_context"],
    context={"title": node.title, "act": node.act, "beat_phase": node.beat_phase},
    scope="writing.outline_enrichment",
    tenant_id=user.pk,
    instance=node.outline_version.project,
)
```

### Django HTMX Mixin

```python
from fieldprefill.django import PrefillViewMixin

class MyEditView(LoginRequiredMixin, PrefillViewMixin, UpdateView):
    prefill_action_code = "ex_doc_prefill"
    prefill_scope = "explosionsschutz.ex_doc"
```

## Architecture

```
App registers retrievers          fieldprefill orchestrates           aifw calls LLM
─────────────────────────    →    ─────────────────────────    →    ──────────────
@register_retriever("sds")        1. get_context_texts()             sync_completion()
@register_retriever("gbu")        2. build_messages()                completion()
register_system_prompt(...)       3. call_llm_sync/async()
                                  4. PrefillResult
```

## License

MIT
