Skip to content
Closed
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
3 changes: 2 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
# DS4 / DwarfStar local OpenAI-compatible server
LEAN_AI_BASE_URL=http://127.0.0.1:8000/v1
LEAN_AI_API_KEY=local-development
# Model used in the thesis experiment
LEAN_AI_MODEL=deepseek-v4-flash
LEAN_AI_TIMEOUT=7200
LEAN_AI_RETRIES=3
LEAN_AI_BACKOFF=5
LEAN_MAX_BANDO_CHARS=40000

3 changes: 3 additions & 0 deletions NOTICE
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,6 @@ Copyright 2026 Antonio De Luca
This distribution includes a research corpus derived from third-party public-sector
documents. Apache-2.0 applies to original project code and does not replace the terms
or attribution requirements of those source documents.

The graph image in docs/assets/welfaregraph-g1.jpeg is an experimental project
output supplied by the thesis author.
125 changes: 88 additions & 37 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,38 +2,89 @@

**Formalizzazione e prototipo eseguibile per la classificazione semantica dei bandi e l'associazione guidata tra bandi e soggetti giuridici.**

![Grafo operativo G1 prodotto nella sperimentazione](docs/assets/welfaregraph-g1.jpeg)

*Grafo operativo G1 ottenuto nella sperimentazione parziale sul dominio dei bandi. La versione navigabile e gli artefatti strutturati sono disponibili in [`examples/results`](examples/results/).*

WelfareGraph raccoglie il codice, i questionari e gli artefatti sperimentali sviluppati per la tesi magistrale sul welfare data-driven. Il progetto traduce in Python i concetti formalizzati in Lean in [mathprompt](https://github.com/francescoantoniodeluca/mathprompt): domini semantici, grafi operativi di differenziazione, firme domanda-risposta, regole trans-dominio e inferenza guidata dal dominio target.

Questa repository contiene l'implementazione reale utilizzata nella sperimentazione, non un prodotto commerciale né un sistema automatico di decisione.
Questa repository contiene l'implementazione reale utilizzata nella sperimentazione. È un prototipo di ricerca, non un prodotto commerciale né un sistema automatico di decisione.

## Stato della sperimentazione

La sperimentazione è **parziale** e riguarda principalmente il dominio `D1_bandi`:

- raccolta e filtro dei documenti;
- costruzione del questionario base D1;
- classificazione e attraversamento del grafo operativo G1;
- produzione e confronto delle firme operative dei bandi.

La seconda fase non è stata completata empiricamente. Manca la progettazione, la stabilizzazione e l'uso su profili reali del **secondo questionario D2 dedicato agli enti**. Questo questionario dovrà semplificare il questionario base selezionando un insieme ridotto di domande sulle caratteristiche dell'organizzazione, sufficiente a indurre soltanto i requisiti D1 pertinenti. Di conseguenza, matching ente-bando, ranking finale e valutazione human-in-the-loop restano sviluppi successivi.

Il file [`questionario_D2_estrazione_requisiti_normalizzato.json`](questionnaires/questionario_D2_estrazione_requisiti_normalizzato.json) conserva una bozza separata di schema per l'estrazione dei requisiti dei bandi. Le sue 45 domande **non costituiscono** il questionario D2 per i soggetti giuridici già validato e utilizzato nella sperimentazione.

## Modello utilizzato: DeepSeek V4 Flash tramite DS4

Tutte le fasi sperimentali che richiedevano inferenza linguistica sono state eseguite con **DeepSeek V4 Flash**, servito localmente tramite **[DS4 / DwarfStar](https://github.com/antirez/ds4)**, il motore di inferenza open source sviluppato da **Salvatore Sanfilippo (antirez)**.

In termini tecnici, DeepSeek V4 Flash è il modello linguistico e DS4 è il runtime che lo esegue ed espone attraverso un endpoint OpenAI-compatible. Nella sperimentazione questa configurazione è stata usata per:

## Cosa implementa
- classificare i documenti come `BANDO` o `ALTRO` e disambiguare più candidati;
- rispondere alle domande del questionario D1 durante l'attraversamento del grafo;
- proporre domande discriminanti quando più bandi mantenevano la stessa firma;
- generare, a livello prototipale, domande e regole trans-dominio.

Le richieste sono state eseguite a temperatura zero, con output JSON vincolato quando previsto. I test automatici utilizzano invece un client simulato e non misurano le prestazioni reali di DS4 o del modello.

## Cosa implementa il codice

La pipeline è articolata in quattro algoritmi:

1. **`build_g1`** costruisce il dominio `D1_bandi` e il grafo operativo `G1`, partendo dal questionario oppure generando domande con un modello linguistico.
1. **`build_g1`** costruisce il dominio `D1_bandi` e il grafo operativo `G1`, partendo dal questionario oppure generando domande con il modello.
2. **`infer_g1`** attraversa `G1` per un singolo bando e ne calcola la firma operativa, cioè l'insieme delle coppie domanda-risposta raggiunte.
3. **`build_induction_objects`** costruisce il dominio `D2_soggetti_giuridici`, le regole trans-dominio e gli insiemi minimi di premesse che inducono risposte in `G1`.
4. **`associate_legal_subject`** acquisisce il profilo del soggetto, induce progressivamente una traccia in `G1` e restituisce i bandi compatibili con quella traccia.
3. **`build_induction_objects`** predispone domande D2, regole trans-dominio e insiemi di premesse che possono indurre risposte in `G1`.
4. **`associate_legal_subject`** contiene il prototipo di inferenza da un profilo del soggetto verso i bandi compatibili.

Gli algoritmi 3 e 4 sono presenti e coperti da test deterministici, ma non equivalgono a una sperimentazione D2 completata: il questionario semplificato degli enti non è stato ancora stabilizzato né applicato a un campione reale.

Il questionario sperimentale D1 contiene 74 domande; il questionario normalizzato di estrazione D2 ne contiene 45. Il corpus incluso contiene 219 testi di bandi e avvisi raccolti da fonti pubbliche. La suite automatica comprende 89 test.
Il questionario base D1 contiene 74 domande, 209 risposte e 192 archi dichiarati. Il corpus versionato contiene 219 testi di bandi e avvisi raccolti da fonti pubbliche. La suite automatica comprende 89 test.

## Architettura del flusso

```mermaid
flowchart LR
A["Portali pubblici"] --> B["Scraping e download"]
B --> C["Filtro documentale ed estrazione testo"]
C --> D["Corpus D1"]
Q["Questionario D1"] --> G["build_g1"]
D --> G
G --> S["infer_g1: firme operative"]
G --> I["build_induction_objects"]
I --> P["Domande e regole D2"]
P --> M["associate_legal_subject"]
S --> M
M --> R["Bandi compatibili"]
subgraph E["Fase sperimentata: dominio D1"]
A["Portali pubblici"] --> B["Scraping e download"]
B --> C["Filtro ed estrazione testo"]
C --> D["Corpus D1"]
Q["Questionario base D1"] --> G["build_g1"]
D --> G
G --> S["infer_g1: firme operative"]
S --> V["Validazione e confronto dei vettori"]
end
G -. "fase 2 non realizzata" .-> I["Questionario semplificato D2 enti"]
I -.-> M["Matching e ranking human-in-the-loop"]
```

## Grafo e risultati della run inclusa

L'artefatto [`g1_graph.json`](examples/results/g1_graph.json) descrive un grafo radicato e aciclico con:

- 171 istanze di nodo e 170 archi;
- una radice, `q_n0`, dalla quale sono raggiungibili tutti i nodi;
- 68 nodi terminali;
- 31 identificatori di domanda distinti e 140 nodi `__sep`, introdotti per riusare domande in rami diversi senza creare cicli.

Il report delle 219 firme operative mostra:

- 219 firme strutturalmente valide;
- 143 firme distinte;
- 99 bandi con firma univoca;
- 120 bandi raccolti in 44 gruppi di firme duplicate, con un gruppo massimo di 7 bandi;
- 79 classificazioni terminali `FIN`, 50 `APP`, 40 `ACC`, 36 `MAN` e 14 `MIX`.

Questi risultati dimostrano l'esecuzione della classificazione D1, ma mostrano anche che la differenziazione non è completa. Non costituiscono una validazione del matching con gli enti né un ranking empirico. Metriche, metodo di calcolo e limiti sono documentati in [`docs/EXPERIMENTAL_RESULTS.md`](docs/EXPERIMENTAL_RESULTS.md).

## Avvio rapido

Richiede Python 3.11 o successivo.
Expand All @@ -47,7 +98,7 @@ pytest

I test usano un client AI simulato e non richiedono rete né credenziali.

Per eseguire la pipeline reale su quattro campioni:
Per eseguire la pipeline su quattro campioni con un server DS4 locale:

```bash
export LEAN_AI_BASE_URL=http://127.0.0.1:8000/v1
Expand All @@ -60,57 +111,57 @@ welfaregraph \
--output-prefix results/
```

L'endpoint deve essere compatibile con l'API OpenAI `/chat/completions` e supportare output JSON vincolato. La temperatura usata dal client è zero.
L'endpoint deve essere compatibile con `/v1/chat/completions` e supportare output JSON vincolato.

## Struttura

```text
lean_prompt_thesis/ Package Python e test dei quattro algoritmi
formal/ Specifica Lean sperimentale
questionnaires/ Questionari D1 e D2, inclusi i casi ridotti
questionnaires/ Questionario D1, bozze e casi ridotti
data/corpus/ Corpus testuale di 219 documenti
data/mini/ Quattro campioni piccoli per prove rapide
scripts/ Pipeline, esempio e analisi dei vettori
tools/scraper/ Raccolta, selezione ed estrazione dei documenti
examples/results/ Artefatti rappresentativi prodotti dalla ricerca
docs/ Architettura, metodo, limiti e roadmap
examples/results/ Grafo, firme e report della sperimentazione D1
docs/ Architettura, metodo, risultati, limiti e roadmap
```

## Artefatti principali

- `questionnaires/questionario_D1_bandi_strutturato_VALID.json`: tassonomia operativa e grafo iniziale D1.
- `questionnaires/questionario_D2_estrazione_requisiti_normalizzato.json`: schema per finalità, beneficiari, requisiti, territorio, attività, partenariati, dati finanziari, spese, premialità, scadenze, documenti e obblighi.
- `examples/results/g1_graph.json`: grafo sperimentale generato.
- `examples/results/report_vettori.csv`: confronto delle firme operative dei 219 documenti.
- `examples/results/grafo_percorso.mmd`: visualizzazione Mermaid delle firme e dei percorsi.
- [`questionario_D1_bandi_strutturato_VALID.json`](questionnaires/questionario_D1_bandi_strutturato_VALID.json): questionario base e grafo iniziale D1.
- [`questionario_D2_estrazione_requisiti_normalizzato.json`](questionnaires/questionario_D2_estrazione_requisiti_normalizzato.json): bozza di schema di estrazione, non questionario degli enti validato.
- [`g1_graph.json`](examples/results/g1_graph.json): grafo operativo prodotto nella run inclusa.
- [`report_vettori.csv`](examples/results/report_vettori.csv): confronto delle firme operative dei 219 documenti.
- [`grafo_percorso.mmd`](examples/results/grafo_percorso.mmd): rappresentazione Mermaid dei percorsi.

## Configurazione del client AI

| Variabile | Default | Funzione |
|---|---|---|
| `LEAN_AI_BASE_URL` | `http://127.0.0.1:8000/v1` | Endpoint OpenAI-compatible |
| `LEAN_AI_BASE_URL` | `http://127.0.0.1:8000/v1` | Endpoint DS4 OpenAI-compatible |
| `LEAN_AI_API_KEY` | `local-development` | Credenziale dell'endpoint locale |
| `LEAN_AI_MODEL` | `deepseek-v4-flash` | Modello usato |
| `LEAN_AI_MODEL` | `deepseek-v4-flash` | Modello usato nella sperimentazione |
| `LEAN_AI_TIMEOUT` | `7200` | Timeout per richiesta, in secondi |
| `LEAN_AI_RETRIES` | `3` | Tentativi su errori transitori |
| `LEAN_AI_BACKOFF` | `5` | Backoff lineare, in secondi |
| `LEAN_MAX_BANDO_CHARS` | `40000` | Limite del testo inviato per domanda |

## Stato scientifico e limiti
## Limiti scientifici

- Il prototipo implementa classificazione, costruzione del grafo, firme operative e associazione `D2 -> G1`.
- Il matching esplicito con indicatori territoriali e il ranking spiegabile sono sviluppi successivi, non funzionalità già validate in questo codice.
- Le risposte del modello possono ricadere su fallback deterministici: i log e gli artefatti devono essere controllati.
- La specifica Lean inclusa è un artefatto sperimentale di corrispondenza dei tipi; la specifica teorica estesa resta nel progetto `mathprompt`.
- I risultati inclusi documentano una sperimentazione e non costituiscono una valutazione giuridica dell'ammissibilità a un bando.
- La run inclusa consolida D1, non l'intera metodologia D1-D2.
- Il questionario semplificato D2 per gli enti, il matching su profili reali e il ranking spiegabile non sono risultati già validati.
- Le firme duplicate indicano che il grafo non ha ancora raggiunto la differenziazione completa del corpus.
- Le risposte del modello possono ricadere su fallback deterministici: log e artefatti devono essere controllati.
- La specifica Lean inclusa è un artefatto sperimentale; la specifica teorica estesa resta nel progetto `mathprompt`.
- I risultati non costituiscono una valutazione giuridica dell'ammissibilità a un bando.

## Dati e responsabilità

I documenti del corpus derivano da fonti pubbliche e sono inclusi per riproducibilità della ricerca. La licenza Apache-2.0 si applica al codice originale della repository; non modifica eventuali diritti, termini o obblighi di attribuzione dei documenti di terzi. Prima di riutilizzare o ridistribuire il corpus, verificare la fonte ufficiale e la versione vigente.

Il sistema deve restare human-in-the-loop: l'associazione prodotta orienta l'analisi, ma la verifica dei requisiti e la decisione finale competono a persone responsabili.
Il sistema deve restare human-in-the-loop: l'associazione prodotta può orientare l'analisi, ma la verifica dei requisiti e la decisione finale competono a persone responsabili.

## Licenza

Codice rilasciato con licenza Apache-2.0. Vedi [LICENSE](LICENSE).

8 changes: 6 additions & 2 deletions docs/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@

Lo scraper mantiene stato incrementale per fonte, limita i PDF a 50 MB, controlla il tipo di contenuto e separa download, selezione del documento ed estrazione testuale.

### Modello e runtime DS4

Il prototipo usa DeepSeek V4 Flash servito localmente tramite [DS4 / DwarfStar](https://github.com/antirez/ds4), sviluppato da Salvatore Sanfilippo. Il confine applicativo è un endpoint OpenAI-compatible configurabile tramite variabili d'ambiente. DS4 è il runtime di inferenza; DeepSeek V4 Flash è il modello utilizzato.

### Dominio D1 e grafo G1

Il questionario D1 definisce domande, risposte, metadata e grafo iniziale. Il loader valida unicità degli identificatori, coerenza domanda-risposta, radici e archi. `build_g1` estende il grafo quando due campioni non sono ancora distinguibili, preservando aciclicità e assenza di domande ripetute sul percorso.
Expand All @@ -23,7 +27,7 @@ Il questionario D1 definisce domande, risposte, metadata e grafo iniziale. Il lo

### Induzione trans-dominio

`build_induction_objects` costruisce domande D2 e insiemi minimi di premesse che supportano risposte operative in G1. `associate_legal_subject` acquisisce soltanto le informazioni D2 rilevanti per i target raggiungibili, riusa le risposte già note e associa i campioni D1 compatibili con la traccia indotta.
`build_induction_objects` e `associate_legal_subject` predispongono a livello prototipale domande D2, insiemi minimi di premesse e inferenza guidata verso G1. La sperimentazione non ha però completato il questionario semplificato degli enti né validato queste componenti su profili organizzativi reali.

### Persistenza

Expand All @@ -50,5 +54,5 @@ Il questionario D1 definisce domande, risposte, metadata e grafo iniziale. Il lo
- L'output LLM viene validato strutturalmente e ritentato, ma resta fallibile.
- Alcuni errori del modello attivano fallback deterministici; i log devono renderli visibili.
- Il risultato è compatibilità semantica rispetto alla configurazione, non ammissibilità giuridica.
- Gli artefatti empirici disponibili riguardano D1; D2 e ranking restano una fase successiva.
- Il prototipo non tratta dati individuali dei beneficiari.

Loading
Loading