Files
boc/projects/landvex/datafabrik/extraktor/extraktor.py
T
Bernt f4f853d94b landvex: Datafabrik + Vision + Infrastruktur för 50GB skalning
Datafabrik:
- Skördare: crawler, källvitlista, upphandlingsskördare
- Extraktor: LLM-baserad schemastyrd extraktion
- Upplösare: Entitetsupplösning och deduplicering
- Köer: Schemalagd / kunddriven / fält
- Agentorkestrering: 20+ parallella agenter

Vision:
- Identify-modell: ResNet50 + kontrastivt lärande
- Träningspipeline: NT-Xent loss
- Vektordatabas: FAISS för snabb sökning
- OCR-pipeline: Typskyltsläsning

Infrastruktur:
- Docker Compose production
- Terraform för AWS ECS
- Prometheus + Grafana monitorering
- Neo4j + FAISS + MinIO + Redis
2026-07-05 06:25:51 +00:00

132 lines
4.6 KiB
Python

#!/usr/bin/env python3
"""
Landvex Extraktor — LLM-baserad schemastyrd extraktion
Dokument in, strukturerade fakta ut.
"""
import json
import os
from pathlib import Path
from typing import List, Dict, Optional
from datetime import datetime
from openai import AsyncOpenAI
# Schema för extraktion (från lvx-objekt-schema.json)
EXTRAKTIONS_SCHEMA = {
"objektklass": {
"required": ["lvx_id", "posttyp", "namn", "doman", "proveniens"],
"fields": [
"lvx_id", "posttyp", "slug", "namn", "doman", "parent", "tier",
"identitet", "teknik", "historik", "geografi", "standarder",
"ai", "problem", "dokumentation", "relationer", "proveniens"
]
},
"produktmodell": {
"required": ["lvx_id", "posttyp", "namn", "doman", "parent", "proveniens"],
"fields": [
"lvx_id", "posttyp", "slug", "namn", "doman", "parent", "tier",
"identitet", "teknik", "historik", "geografi", "standarder",
"ai", "problem", "dokumentation", "relationer", "proveniens"
]
}
}
EXTRAKTIONS_PROMPT = """Du är Landvex Extraktor — en noggrann forskarassistent specialiserad på infrastrukturobjekt.
DIN UPPGIFT: Analysera följande dokument och extrahera strukturerade fakta om infrastrukturobjekt.
REGLER:
1. Extrahera ENDAST fakta som finns i dokumentet — uppfinn inget
2. Varje faktum måste ha en källa (URL eller dokumentreferens)
3. Använd Landvex-schemat strikt
4. Om något är osäkert, markera med låg konfidens
5. Problem/Kända fel kräver alltid källa
OUTPUT: JSON enligt följande struktur:
{
"kandidater": [
{
"atgard": "ny" | "uppdatera",
"posttyp": "objektklass" | "produktmodell",
"post": { ... },
"patch": { ... },
"verifieringsniva_forslag": "obekraftad" | "kallbelagd" | "faltverifierad" | "tillverkarbekraftad",
"kallor": [
{"titel": "...", "url": "...", "hamtad": "2026-07-05"}
]
}
]
}
DOKUMENT:
{content}
"""
class LandvexExtraktor:
def __init__(self, api_key: Optional[str] = None):
self.client = AsyncOpenAI(api_key=api_key or os.getenv("OPENAI_API_KEY"))
self.model = "gpt-4o-mini" # Kostnadseffektiv för volym
async def extrahera(self, dokument: str, url: str, doman: str) -> dict:
"""Extrahera strukturerade fakta från ett dokument."""
prompt = EXTRAKTIONS_PROMPT.format(content=dokument[:15000]) # Begränsa längd
try:
response = await self.client.chat.completions.create(
model=self.model,
messages=[
{"role": "system", "content": "Du är Landvex Extraktor. Extrahera strukturerade fakta om infrastrukturobjekt."},
{"role": "user", "content": prompt}
],
response_format={"type": "json_object"},
temperature=0.1, # Låg för determinism
)
resultat = json.loads(response.choices[0].message.content)
# Lägg till proveniens
for kand in resultat.get("kandidater", []):
kand.setdefault("kallor", []).append({
"titel": f"Extraherat från {url}",
"url": url,
"hamtad": datetime.utcnow().isoformat()
})
return resultat
except Exception as e:
print(f" ⚠️ Extraktionsfel: {e}")
return {"kandidater": [], "fel": str(e)}
async def extrahera_batch(self, dokument: List[dict]) -> List[dict]:
"""Extrahera från flera dokument parallellt."""
import asyncio
uppgifter = [
self.extrahera(d["html"], d["url"], d.get("doman", "TRP"))
for d in dokument
]
resultat = await asyncio.gather(*uppgifter, return_exceptions=True)
return [r for r in resultat if not isinstance(r, Exception)]
async def main():
"""Demo: extrahera från testdokument."""
extraktor = LandvexExtraktor()
test_doc = """
ABB Kabeldon CDC-LT är ett lågspänningskabelskåp för utomhusbruk.
Material: Varmförzinkad stålplåt, IP34D enligt SS-EN 60529.
Standard: SS-EN 61439-5 (provnings- och konstruktionskrav).
Tillverkare: ABB Kabeldon, Alingsås.
Lås: Trekantslås standard, cylinderlås som tillval.
"""
resultat = await extraktor.extrahera(test_doc, "https://example.com/test", "ELN")
print(json.dumps(resultat, ensure_ascii=False, indent=2))
if __name__ == "__main__":
import asyncio
asyncio.run(main())