Skip to content

Retrieves and transforms Swedish legislation published in the Swedish Code of Statutes (SFS), into multiple output formats such as Markdown (with temporal Selex tags), Git version history, and HTML.

License

Notifications You must be signed in to change notification settings

se-lex/sfs-processor

Repository files navigation

sfs-processor - Verktyg för konvertering av Svensk författningssamling

🇬🇧 Switch to English


Detta repository innehåller Python-script för att konvertera SFS-författningar (Svensk författningssamling) från JSON-format till Markdown med temporala taggar, HTML, Git och andra format.

Note

Detta är en del av SE-Lex, läs mer om projektet här.

SFS-författningar exporteras till https://github.com/se-lex/sfs och publiceras också som HTML på https://selex.se med stöd för EU:s juridiska identifieringsstandard (ELI).

Installation

  1. Se till att du har Python 3.11 eller senare installerat
  2. Installera nödvändiga beroenden:
pip install -r requirements.txt

Snabbstart

Konvertera JSON-filer med författningar till Markdown:

python sfs_processor.py --input sfs_json --output output/md --formats md-markers

Output-format

Verktyget kan generera författningar i flera olika format, beroende på användningsområde:

Markdown-format

  • md-markers (förvalt): Markdown med semantiska <section>-taggar och selex-attribut för juridisk status och temporal hantering
  • md: Rena Markdown-filer med normaliserade rubriknivåer, lämpliga för visning och läsning. Utgår från ett target-date (förvalt: dagens datum) för att visa hur lagen ser ut vid den tidpunkten

Git-format

  • git: Exporterar författningar som Git-commits med historiska datum, vilket skapar en versionshistorik av lagstiftningen

HTML-format

  • html: Genererar HTML-filer i ELI-struktur (/eli/sfs/{år}/{nummer}/index.html) för webbpublicering
  • htmldiff: Som HTML men inkluderar även separata versioner för varje ändringsförfattning

HTML-filer kan publiceras via:

  • Cloudflare R2: Med html-export-workflow.yml (kräver R2-credentials)
  • GitHub Pages: Med github-pages-workflow.yml (enklare setup, kräver aktiverad GitHub Pages)

Vektor-format (för semantisk sökning)

  • vector: Konverterar författningar till vektorembeddings för semantisk sökning och RAG-applikationer. Använder OpenAI:s text-embedding-3-large modell (3072 dimensioner) och stödjer lagring i PostgreSQL (pgvector), Elasticsearch eller JSON-fil.

Exempel på att kombinera flera format:

python sfs_processor.py --input sfs_json --output output --formats md,html,git

Hämta källdata

För att konvertera författningar behöver du först ladda ner JSON-data:

Ladda ner alla författningar från Regeringskansliet

python downloaders/download_sfs_docs.py --ids all --source rkrattsbaser

Ladda ner specifika författningar

python downloaders/download_sfs_docs.py --ids "2024:675,2024:700" --source rkrattsbaser

Nedladdade filer sparas som standard i katalogen sfs_docs. Du kan ange annan katalog med --out parametern.

Användning

Grundläggande konvertering

Konvertera alla JSON-filer i en katalog till Markdown:

python sfs_processor.py --input sfs_json --output output/md --formats md-markers

Struktur av genererade Markdown-filer

Beroende på vilket format du väljer får du olika strukturer:

Format: md-markers (förvalt)

Markdown-filer med bevarad semantisk struktur genom <article> och <section>-taggar:

  • <article>: Omsluter hela författningen och kan innehålla temporala attribut (ikraft_datum, upphor_datum, etc.)
  • <section class="avdelning">: Omsluter avdelningar (divisions) som överordnad strukturell enhet
  • <section class="kapitel">: Omsluter kapitel som strukturell enhet med underliggande paragrafer
  • <section class="paragraf">: Omsluter varje paragraf (§) som en avgränsad juridisk bestämmelse
<article selex:status="ikraft" selex:ikraft_datum="2025-01-01">

  # Lag (2024:123) om exempel

  <section class="avdelning" id="avd1">
  ## AVDELNING I. ALLMÄNNA BESTÄMMELSER

    <section class="kapitel" id="inledande-bestammelser">
    ### Inledande bestämmelser

      <section class="paragraf" id="inledande-bestammelser.1">
      #### 1 §
      Innehållet i paragrafen...
      </section>

    </section>

  </section>

</article>

Denna semantiska struktur bevarar dokumentets logiska uppbyggnad och möjliggör automatisk bearbetning, analys, och navigation av författningstexten. ID-attributen gör det möjligt att länka direkt till specifika rubriker och paragrafer (t.ex. #inledande-bestammelser.1). Taggarna kan även användas för CSS-styling och JavaScript-funktionalitet.

OBS! Trots HTML-taggarna är filerna fortfarande fullt läsbara som Markdown :)

Format: md

Rena Markdown-filer med normaliserade rubriknivåer, utan section-taggar:

# Lag (2024:123) om exempel

## Inledande bestämmelser

### 1 §

Innehållet i paragrafen...

### 2 §

Mer innehåll...

Detta format är lämpligt för enkel visning och läsning, utan metadata eller temporal hantering.

Selex-attribut för juridisk status och datum

Förutom CSS-klasser använder <section>-taggarna även selex:-attribut för att hantera juridisk status och datum. Dessa attribut möjliggör filtrering av innehåll baserat på ikraftträdande- och upphörandedatum:

  • selex:status: Anger sektionens juridiska status

    • ikraft: Sektionen innehåller ikraftträdanderegler (konverterat från t.ex. "/Träder i kraft I:2025-01-01")
    • upphavd: Sektionen är upphävd (konverterad från ifall rubrik innehåller "upphävd" eller "/Upphör att gälla")
  • selex:ikraft_datum: Datum då sektionen träder ikraft (format: YYYY-MM-DD)

  • selex:upphor_datum: Datum då sektionen upphör att gälla (format: YYYY-MM-DD)

  • selex:ikraft_villkor: Villkor för ikraftträdande (när inget specifikt datum anges)

Exempel på selex-attribut:

<section class="kapitel" selex:status="ikraft" selex:ikraft_datum="2025-01-01">
### 1 § En paragraf
...
</section>

<section class="paragraf" selex:status="upphavd" selex:upphor_datum="2023-12-31">
#### 2 § En paragraf 
...
</section>

<section class="kapitel" selex:status="ikraft" selex:ikraft_villkor="den dag regeringen bestämmer">
### 3 § Rubrik på villkorad ikraftträdande
...
</section>

Dessa attribut används automatiskt av systemets datumfiltrering för att skapa versioner av författningar som gäller vid specifika tidpunkter. Sektioner med selex:upphor_datum som har passerat tas bort, och sektioner med selex:ikraft_datum som ännu inte har kommit tas bort från den aktuella versionen.

Temporal processing för olika format

Systemet hanterar temporal processing (tidsbaserad filtrering) olika beroende på vilket format som används:

  • md-markers (förvalt): Bevarar selex-taggar och hoppar över temporal processing. Detta gör att alla temporal attribut behålls för senare bearbetning. Rekommenderas för att bevara all juridisk metadata.

  • md: Tillämpar temporal processing med dagens datum som målpunkt. Detta är viktigt att förstå:

    • Upphävda bestämmelser (med selex:upphor_datum före dagens datum) tas bort
    • Bestämmelser som ännu inte trätt i kraft (med selex:ikraft_datum efter dagens datum) tas bort
    • Selex-taggar tas bort efter filtrering
    • Resultatet blir en "ren" Markdown-vy av hur lagen ser ut idag
    • Obs: Eftersom temporal filtrering används automatiskt, kan innehåll försvinna om det är upphävt eller ej ikraftträtt
  • git: Hoppar över temporal processing i huvudbearbetningen. Temporal hantering sköts separat i git-arbetsflödet för att skapa historiska commits.

  • html och htmldiff: Tillämpar temporal processing med dagens datum innan HTML-generering, liknande md-format.

  • vector: Tillämpar temporal processing med dagens datum (eller angivet --target-date) innan vektorgenerering. Detta säkerställer att endast gällande regelverk inkluderas i vektordatabasen.

Exempel med target-date

För att se hur en lag såg ut vid ett specifikt datum:

# Se hur lagen såg ut 2023-01-01
python sfs_processor.py --input sfs_json --output output/md --formats md --target-date 2023-01-01

Detta är användbart för att skapa historiska versioner eller för att förstå hur lagen såg ut vid en viss tidpunkt.

Kommandoradsalternativ

python sfs_processor.py [--input INPUT] [--output OUTPUT] [--formats FORMATS] [--filter FILTER] [--target-date DATE] [--no-year-folder] [--verbose]

Parametrar

  • --input: Input-katalog med JSON-filer (default: "sfs_json")
  • --output: Output-katalog för konverterade filer (default: "SFS")
  • --formats: Utdataformat att generera, kommaseparerat. Stödjer: md-markers, md, git, html, htmldiff, vector (default: "md-markers")
    • md-markers: Generera markdown-filer med section-taggar bevarade
    • md: Generera rena markdown-filer utan section-taggar
    • git: Aktivera Git-commits med historiska datum
    • html: Generera HTML-filer i ELI-struktur (endast grunddokument)
    • htmldiff: Generera HTML-filer i ELI-struktur med ändringsversioner
    • vector: Generera vektorembeddings för semantisk sökning
  • --filter: Filtrera filer efter år (YYYY) eller specifik beteckning (YYYY:NNN). Kan vara kommaseparerad lista.
  • --target-date: Datum (YYYY-MM-DD) för temporal filtrering, baserat på selex-taggar. Används med md, html, htmldiff och vector format för att filtrera innehåll baserat på giltighetsdatum. Om inte angivet används dagens datum. Exempel: --target-date 2023-01-01
  • --no-year-folder: Skapa inte årbaserade undermappar för dokument
  • --verbose: Visa detaljerad information om bearbetningen

Vektor-specifika parametrar

  • --vector-backend: Backend för vektorlagring (default: "json")
    • json: Spara till JSON-fil (för test/utveckling)
    • postgresql: PostgreSQL med pgvector-extension
    • elasticsearch: Elasticsearch med dense_vector
  • --vector-chunking: Strategi för att dela upp dokument (default: "paragraph")
    • paragraph: Dela per paragraf (§) - bevarar juridisk struktur
    • chapter: Dela per kapitel - större kontext
    • section: Dela per selex-sektion
    • semantic: Semantiska gränser med överlapp
    • fixed_size: Fast tokenantal med överlapp
  • --embedding-model: Embedding-modell (default: "text-embedding-3-large")
  • --vector-mock: Använd mock-embeddings för test utan OpenAI API-nyckel

Vektorexport för semantisk sökning

Vektorformatet (--formats vector) konverterar författningar till vektorembeddings som kan användas för semantisk sökning, RAG-applikationer (Retrieval-Augmented Generation) och AI-assistenter.

Hur det fungerar

  1. Temporal filtrering: Endast gällande regelverk inkluderas (samma som md/html mode)
  2. Intelligent chunking: Dokument delas upp på ett sätt som bevarar juridisk struktur
  3. Embedding-generering: Text konverteras till vektorer med OpenAI text-embedding-3-large
  4. Lagring: Vektorer sparas till vald backend med fullständig metadata

Exempel

# Test med mock-embeddings (utan API-nyckel)
python sfs_processor.py --formats vector --vector-mock --filter 2024:100

# Produktion med OpenAI (kräver OPENAI_API_KEY miljövariabel)
python sfs_processor.py --formats vector --filter 2024

# Med PostgreSQL/pgvector backend
python sfs_processor.py --formats vector --vector-backend postgresql

# Med kapitel-chunking för större kontext
python sfs_processor.py --formats vector --vector-chunking chapter

Backends

Backend Användning Krav
json Test/utveckling Inga
postgresql Produktion PostgreSQL 12+ med pgvector
elasticsearch Produktion Elasticsearch 8.0+

Metadata som sparas

Varje vektor-chunk innehåller:

  • document_id: Beteckning (t.ex. "2024:100")
  • chapter: Kapitelreferens (t.ex. "1 kap.")
  • paragraph: Paragrafreferens (t.ex. "1 §")
  • departement: Ansvarigt departement
  • effective_date: Ikraftträdande-datum

Bidra

Vi välkomnar bidrag från communityn! 🙌

About

Retrieves and transforms Swedish legislation published in the Swedish Code of Statutes (SFS), into multiple output formats such as Markdown (with temporal Selex tags), Git version history, and HTML.

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Contributors 2

  •  
  •  

Languages