Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 68 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ Verktyget kan generera författningar i flera olika format, beroende på använd
- **`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

### 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:

```bash
Expand Down Expand Up @@ -186,6 +190,8 @@ Systemet hanterar temporal processing (tidsbaserad filtrering) olika beroende p

- **`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:
Expand All @@ -207,17 +213,77 @@ python sfs_processor.py [--input INPUT] [--output OUTPUT] [--formats FORMATS] [-

- `--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 (default: "md-markers")
- `--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` och `htmldiff` format för att filtrera innehåll baserat på giltighetsdatum. Om inte angivet används dagens datum för `md`-format. Exempel: `--target-date 2023-01-01`
- `--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

```bash
# 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
- `ikraft_datum`: Ikraftträdandedatum

## Bidra

Vi välkomnar bidrag från communityn! 🙌
Expand Down
23 changes: 23 additions & 0 deletions exporters/vector/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#!/usr/bin/env python3
"""
Vector export functionality for SFS documents.

This module provides tools for converting Swedish legal documents (SFS)
to vector embeddings suitable for semantic search and retrieval.

The vector exporter applies temporal filtering (like md/html mode) to ensure
only current regulations are included in the vector store.
"""

from exporters.vector.vector_export import create_vector_documents, VectorExportConfig
from exporters.vector.chunking import chunk_document, ChunkingStrategy
from exporters.vector.embeddings import EmbeddingProvider, get_embedding_provider

__all__ = [
'create_vector_documents',
'VectorExportConfig',
'chunk_document',
'ChunkingStrategy',
'EmbeddingProvider',
'get_embedding_provider',
]
65 changes: 65 additions & 0 deletions exporters/vector/backends/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#!/usr/bin/env python3
"""
Vector store backends for SFS documents.

Supported backends:
- PostgreSQL with pgvector extension
- Elasticsearch with dense_vector
- JSON file (for testing/development)
"""

from exporters.vector.backends.base import VectorStoreBackend, VectorRecord
from exporters.vector.backends.postgresql import PostgreSQLBackend
from exporters.vector.backends.elasticsearch import ElasticsearchBackend
from exporters.vector.backends.json_file import JSONFileBackend

__all__ = [
'VectorStoreBackend',
'VectorRecord',
'PostgreSQLBackend',
'ElasticsearchBackend',
'JSONFileBackend',
]


def get_backend(backend_type: str, **kwargs) -> VectorStoreBackend:
"""
Factory function to get a vector store backend.

Args:
backend_type: Type of backend ("postgresql", "elasticsearch", "json")
**kwargs: Backend-specific configuration

Returns:
A VectorStoreBackend instance

Example:
# PostgreSQL with pgvector
backend = get_backend("postgresql", connection_string="postgresql://...")

# Elasticsearch
backend = get_backend("elasticsearch", hosts=["http://localhost:9200"])

# JSON file for testing
backend = get_backend("json", file_path="vectors.json")
"""
backends = {
"postgresql": PostgreSQLBackend,
"postgres": PostgreSQLBackend,
"pgvector": PostgreSQLBackend,
"elasticsearch": ElasticsearchBackend,
"elastic": ElasticsearchBackend,
"es": ElasticsearchBackend,
"json": JSONFileBackend,
"file": JSONFileBackend,
}

backend_type_lower = backend_type.lower()
if backend_type_lower not in backends:
available = list(set(backends.values()))
raise ValueError(
f"Unknown backend type: {backend_type}. "
f"Available: postgresql, elasticsearch, json"
)

return backends[backend_type_lower](**kwargs)
Loading