feinschliff für pek

This commit is contained in:
Ida Dittrich 2025-12-01 17:24:56 +01:00
parent e0c4193e36
commit 8e2c4adcb5
20 changed files with 1637 additions and 24 deletions

View file

@ -0,0 +1,89 @@
Analyze the following user command and extract the intent, entity, and parameters.
User Command: "wie viele Projekte in Zürich gibt es?"
Available intents:
- CREATE: User wants to create a new entity
- READ: User wants to read/query entities
- UPDATE: User wants to update an existing entity
- DELETE: User wants to delete an entity
- QUERY: User wants to execute a database query (SQL statements)
Available entities and their fields:
**Projekt** (Real estate project):
- id: string (primary key)
- mandateId: string (mandate ID)
- label: string (project designation/name)
- statusProzess: string enum (Eingang, Analyse, Studie, Planung, Baurechtsverfahren, Umsetzung, Archiv)
- perimeter: GeoPolylinie (geographic boundary, JSONB)
- baulinie: GeoPolylinie (building line, JSONB)
- parzellen: List[Parzelle] (plots belonging to project, JSONB)
- dokumente: List[Dokument] (documents, JSONB)
- kontextInformationen: List[Kontext] (context info, JSONB)
**Parzelle** (Plot/parcel):
- id: string (primary key)
- mandateId: string (mandate ID)
- label: string (plot designation)
- strasseNr: string (street and house number)
- plz: string (postal code)
- kontextGemeinde: string (municipality ID, Foreign Key to Gemeinde table)
- bauzone: string (building zone, e.g. W3, WG2)
- az: float (Ausnützungsziffer)
- bz: float (Bebauungsziffer)
- vollgeschossZahl: int (number of allowed full floors)
- gebaeudehoeheMax: float (maximum building height in meters)
- laermschutzzone: string (noise protection zone)
- hochwasserschutzzone: string (flood protection zone)
- grundwasserschutzzone: string (groundwater protection zone)
- parzelleBebaut: JaNein enum (is plot built)
- parzelleErschlossen: JaNein enum (is plot developed)
- parzelleHanglage: JaNein enum (is plot on slope)
**Important relationships:**
- Projekte contain Parzellen (projects have plots)
- Parzelle links to Gemeinde (via kontextGemeinde)
- Gemeinde links to Kanton (via id_kanton)
- Kanton links to Land (via id_land)
- Location queries (city, postal code) should use Parzelle.kontextGemeinde (municipality name will be resolved to ID)
- Projekt does NOT have location fields directly - location is stored in associated Parzellen
Return a JSON object with the following structure:
{
"intent": "CREATE|READ|UPDATE|DELETE|QUERY",
"entity": "Projekt|Parzelle|Dokument|Kanton|Gemeinde|null",
"parameters": {
// Extracted parameters from user input
// For CREATE/UPDATE: include all relevant fields using EXACT field names from above
// For READ: include filter criteria using EXACT field names (id, label, plz, kontextGemeinde, etc.)
// For DELETE: include entity ID if mentioned
// For QUERY: include queryText if SQL is detected
// IMPORTANT: Use only field names that exist in the entity definition above
},
"confidence": 0.0-1.0 // Confidence score for the analysis
}
Examples:
- Input: "Erstelle ein neues Projekt namens 'Hauptstrasse 42'"
Output: {"intent": "CREATE", "entity": "Projekt", "parameters": {"label": "Hauptstrasse 42"}, "confidence": 0.95}
- Input: "Zeige mir alle Projekte"
Output: {"intent": "READ", "entity": "Projekt", "parameters": {}, "confidence": 0.9}
- Input: "Zeige mir Projekte in Zürich" or "Wie viele Projekte in Zürich"
Output: {"intent": "READ", "entity": "Projekt", "parameters": {"location_filter": "Zürich"}, "confidence": 0.9}
Note: For project location queries, use Projekt entity with location_filter parameter
- Input: "Zeige mir Parzellen mit PLZ 8000"
Output: {"intent": "READ", "entity": "Parzelle", "parameters": {"plz": "8000"}, "confidence": 0.95}
- Input: "Aktualisiere Projekt XYZ mit Status 'Planung'"
Output: {"intent": "UPDATE", "entity": "Projekt", "parameters": {"id": "XYZ", "statusProzess": "Planung"}, "confidence": 0.85}
- Input: "SELECT * FROM Projekt WHERE label = 'Test'"
Output: {"intent": "QUERY", "entity": null, "parameters": {"queryText": "SELECT * FROM Projekt WHERE label = 'Test'", "queryType": "sql"}, "confidence": 1.0}
- Input: "Lösche Parzelle ABC"
Output: {"intent": "DELETE", "entity": "Parzelle", "parameters": {"id": "ABC"}, "confidence": 0.9}

View file

@ -0,0 +1,17 @@
```json
{
"intent": "READ",
"entity": "Projekt",
"parameters": {
"location_filter": "Zürich"
},
"confidence": 0.9
}
```
**Analysis:**
- **Intent**: READ - The user wants to query/count existing projects ("wie viele ... gibt es?" = "how many ... are there?")
- **Entity**: Projekt - The user is asking about "Projekte" (projects)
- **Parameters**:
- `location_filter: "Zürich"` - The user wants to filter projects by location (Zürich). Since Projekt doesn't have direct location fields, this will need to be resolved through the associated Parzellen's kontextGemeinde relationship
- **Confidence**: 0.9 - High confidence as the intent and entity are clear, though the query involves a relationship traversal (Projekt → Parzelle → Gemeinde)

View file

@ -0,0 +1,89 @@
Analyze the following user command and extract the intent, entity, and parameters.
User Command: "Erstelle ein neues Projekt in Zürich"
Available intents:
- CREATE: User wants to create a new entity
- READ: User wants to read/query entities
- UPDATE: User wants to update an existing entity
- DELETE: User wants to delete an entity
- QUERY: User wants to execute a database query (SQL statements)
Available entities and their fields:
**Projekt** (Real estate project):
- id: string (primary key)
- mandateId: string (mandate ID)
- label: string (project designation/name)
- statusProzess: string enum (Eingang, Analyse, Studie, Planung, Baurechtsverfahren, Umsetzung, Archiv)
- perimeter: GeoPolylinie (geographic boundary, JSONB)
- baulinie: GeoPolylinie (building line, JSONB)
- parzellen: List[Parzelle] (plots belonging to project, JSONB)
- dokumente: List[Dokument] (documents, JSONB)
- kontextInformationen: List[Kontext] (context info, JSONB)
**Parzelle** (Plot/parcel):
- id: string (primary key)
- mandateId: string (mandate ID)
- label: string (plot designation)
- strasseNr: string (street and house number)
- plz: string (postal code)
- kontextGemeinde: string (municipality ID, Foreign Key to Gemeinde table)
- bauzone: string (building zone, e.g. W3, WG2)
- az: float (Ausnützungsziffer)
- bz: float (Bebauungsziffer)
- vollgeschossZahl: int (number of allowed full floors)
- gebaeudehoeheMax: float (maximum building height in meters)
- laermschutzzone: string (noise protection zone)
- hochwasserschutzzone: string (flood protection zone)
- grundwasserschutzzone: string (groundwater protection zone)
- parzelleBebaut: JaNein enum (is plot built)
- parzelleErschlossen: JaNein enum (is plot developed)
- parzelleHanglage: JaNein enum (is plot on slope)
**Important relationships:**
- Projekte contain Parzellen (projects have plots)
- Parzelle links to Gemeinde (via kontextGemeinde)
- Gemeinde links to Kanton (via id_kanton)
- Kanton links to Land (via id_land)
- Location queries (city, postal code) should use Parzelle.kontextGemeinde (municipality name will be resolved to ID)
- Projekt does NOT have location fields directly - location is stored in associated Parzellen
Return a JSON object with the following structure:
{
"intent": "CREATE|READ|UPDATE|DELETE|QUERY",
"entity": "Projekt|Parzelle|Dokument|Kanton|Gemeinde|null",
"parameters": {
// Extracted parameters from user input
// For CREATE/UPDATE: include all relevant fields using EXACT field names from above
// For READ: include filter criteria using EXACT field names (id, label, plz, kontextGemeinde, etc.)
// For DELETE: include entity ID if mentioned
// For QUERY: include queryText if SQL is detected
// IMPORTANT: Use only field names that exist in the entity definition above
},
"confidence": 0.0-1.0 // Confidence score for the analysis
}
Examples:
- Input: "Erstelle ein neues Projekt namens 'Hauptstrasse 42'"
Output: {"intent": "CREATE", "entity": "Projekt", "parameters": {"label": "Hauptstrasse 42"}, "confidence": 0.95}
- Input: "Zeige mir alle Projekte"
Output: {"intent": "READ", "entity": "Projekt", "parameters": {}, "confidence": 0.9}
- Input: "Zeige mir Projekte in Zürich" or "Wie viele Projekte in Zürich"
Output: {"intent": "READ", "entity": "Projekt", "parameters": {"location_filter": "Zürich"}, "confidence": 0.9}
Note: For project location queries, use Projekt entity with location_filter parameter
- Input: "Zeige mir Parzellen mit PLZ 8000"
Output: {"intent": "READ", "entity": "Parzelle", "parameters": {"plz": "8000"}, "confidence": 0.95}
- Input: "Aktualisiere Projekt XYZ mit Status 'Planung'"
Output: {"intent": "UPDATE", "entity": "Projekt", "parameters": {"id": "XYZ", "statusProzess": "Planung"}, "confidence": 0.85}
- Input: "SELECT * FROM Projekt WHERE label = 'Test'"
Output: {"intent": "QUERY", "entity": null, "parameters": {"queryText": "SELECT * FROM Projekt WHERE label = 'Test'", "queryType": "sql"}, "confidence": 1.0}
- Input: "Lösche Parzelle ABC"
Output: {"intent": "DELETE", "entity": "Parzelle", "parameters": {"id": "ABC"}, "confidence": 0.9}

View file

@ -0,0 +1,17 @@
```json
{
"intent": "CREATE",
"entity": "Projekt",
"parameters": {
"location_filter": "Zürich"
},
"confidence": 0.85
}
```
**Explanation:**
- **Intent**: CREATE - The user wants to create a new project ("Erstelle ein neues Projekt")
- **Entity**: Projekt - The entity type is clearly specified
- **Parameters**:
- `location_filter`: "Zürich" - The user mentions "in Zürich" as the location. Since Projekt doesn't have direct location fields (location is stored in associated Parzellen), I'm using `location_filter` to indicate the intended location context. This will need to be handled by creating associated Parzellen with the appropriate `kontextGemeinde` value.
- **Confidence**: 0.85 - High confidence in intent and entity, slightly lower because the location reference for a new project is indirect (projects get location through their parcels) and no project name/label was provided.

View file

@ -0,0 +1,89 @@
Analyze the following user command and extract the intent, entity, and parameters.
User Command: "wie viele Projekte in zürich gibt es jetzt?"
Available intents:
- CREATE: User wants to create a new entity
- READ: User wants to read/query entities
- UPDATE: User wants to update an existing entity
- DELETE: User wants to delete an entity
- QUERY: User wants to execute a database query (SQL statements)
Available entities and their fields:
**Projekt** (Real estate project):
- id: string (primary key)
- mandateId: string (mandate ID)
- label: string (project designation/name)
- statusProzess: string enum (Eingang, Analyse, Studie, Planung, Baurechtsverfahren, Umsetzung, Archiv)
- perimeter: GeoPolylinie (geographic boundary, JSONB)
- baulinie: GeoPolylinie (building line, JSONB)
- parzellen: List[Parzelle] (plots belonging to project, JSONB)
- dokumente: List[Dokument] (documents, JSONB)
- kontextInformationen: List[Kontext] (context info, JSONB)
**Parzelle** (Plot/parcel):
- id: string (primary key)
- mandateId: string (mandate ID)
- label: string (plot designation)
- strasseNr: string (street and house number)
- plz: string (postal code)
- kontextGemeinde: string (municipality ID, Foreign Key to Gemeinde table)
- bauzone: string (building zone, e.g. W3, WG2)
- az: float (Ausnützungsziffer)
- bz: float (Bebauungsziffer)
- vollgeschossZahl: int (number of allowed full floors)
- gebaeudehoeheMax: float (maximum building height in meters)
- laermschutzzone: string (noise protection zone)
- hochwasserschutzzone: string (flood protection zone)
- grundwasserschutzzone: string (groundwater protection zone)
- parzelleBebaut: JaNein enum (is plot built)
- parzelleErschlossen: JaNein enum (is plot developed)
- parzelleHanglage: JaNein enum (is plot on slope)
**Important relationships:**
- Projekte contain Parzellen (projects have plots)
- Parzelle links to Gemeinde (via kontextGemeinde)
- Gemeinde links to Kanton (via id_kanton)
- Kanton links to Land (via id_land)
- Location queries (city, postal code) should use Parzelle.kontextGemeinde (municipality name will be resolved to ID)
- Projekt does NOT have location fields directly - location is stored in associated Parzellen
Return a JSON object with the following structure:
{
"intent": "CREATE|READ|UPDATE|DELETE|QUERY",
"entity": "Projekt|Parzelle|Dokument|Kanton|Gemeinde|null",
"parameters": {
// Extracted parameters from user input
// For CREATE/UPDATE: include all relevant fields using EXACT field names from above
// For READ: include filter criteria using EXACT field names (id, label, plz, kontextGemeinde, etc.)
// For DELETE: include entity ID if mentioned
// For QUERY: include queryText if SQL is detected
// IMPORTANT: Use only field names that exist in the entity definition above
},
"confidence": 0.0-1.0 // Confidence score for the analysis
}
Examples:
- Input: "Erstelle ein neues Projekt namens 'Hauptstrasse 42'"
Output: {"intent": "CREATE", "entity": "Projekt", "parameters": {"label": "Hauptstrasse 42"}, "confidence": 0.95}
- Input: "Zeige mir alle Projekte"
Output: {"intent": "READ", "entity": "Projekt", "parameters": {}, "confidence": 0.9}
- Input: "Zeige mir Projekte in Zürich" or "Wie viele Projekte in Zürich"
Output: {"intent": "READ", "entity": "Projekt", "parameters": {"location_filter": "Zürich"}, "confidence": 0.9}
Note: For project location queries, use Projekt entity with location_filter parameter
- Input: "Zeige mir Parzellen mit PLZ 8000"
Output: {"intent": "READ", "entity": "Parzelle", "parameters": {"plz": "8000"}, "confidence": 0.95}
- Input: "Aktualisiere Projekt XYZ mit Status 'Planung'"
Output: {"intent": "UPDATE", "entity": "Projekt", "parameters": {"id": "XYZ", "statusProzess": "Planung"}, "confidence": 0.85}
- Input: "SELECT * FROM Projekt WHERE label = 'Test'"
Output: {"intent": "QUERY", "entity": null, "parameters": {"queryText": "SELECT * FROM Projekt WHERE label = 'Test'", "queryType": "sql"}, "confidence": 1.0}
- Input: "Lösche Parzelle ABC"
Output: {"intent": "DELETE", "entity": "Parzelle", "parameters": {"id": "ABC"}, "confidence": 0.9}

View file

@ -0,0 +1,17 @@
```json
{
"intent": "READ",
"entity": "Projekt",
"parameters": {
"location_filter": "zürich"
},
"confidence": 0.9
}
```
**Analysis:**
- **Intent**: READ - The user wants to query/count existing projects ("wie viele Projekte ... gibt es")
- **Entity**: Projekt - The query is about projects ("Projekte")
- **Parameters**:
- `location_filter`: "zürich" - The user is asking about projects in Zürich. Since Projekt doesn't have direct location fields but location is stored in associated Parzellen (via kontextGemeinde), we use the `location_filter` parameter to indicate this geographic filter needs to be resolved through the Parzelle relationship.
- **Confidence**: 0.9 - High confidence. The intent is clear (counting/querying projects), the location is explicitly mentioned, and the temporal indicator "jetzt" (now) suggests current/active projects.

View file

@ -0,0 +1,89 @@
Analyze the following user command and extract the intent, entity, and parameters.
User Command: "wie viele parzellen in zürich gibt es?"
Available intents:
- CREATE: User wants to create a new entity
- READ: User wants to read/query entities
- UPDATE: User wants to update an existing entity
- DELETE: User wants to delete an entity
- QUERY: User wants to execute a database query (SQL statements)
Available entities and their fields:
**Projekt** (Real estate project):
- id: string (primary key)
- mandateId: string (mandate ID)
- label: string (project designation/name)
- statusProzess: string enum (Eingang, Analyse, Studie, Planung, Baurechtsverfahren, Umsetzung, Archiv)
- perimeter: GeoPolylinie (geographic boundary, JSONB)
- baulinie: GeoPolylinie (building line, JSONB)
- parzellen: List[Parzelle] (plots belonging to project, JSONB)
- dokumente: List[Dokument] (documents, JSONB)
- kontextInformationen: List[Kontext] (context info, JSONB)
**Parzelle** (Plot/parcel):
- id: string (primary key)
- mandateId: string (mandate ID)
- label: string (plot designation)
- strasseNr: string (street and house number)
- plz: string (postal code)
- kontextGemeinde: string (municipality ID, Foreign Key to Gemeinde table)
- bauzone: string (building zone, e.g. W3, WG2)
- az: float (Ausnützungsziffer)
- bz: float (Bebauungsziffer)
- vollgeschossZahl: int (number of allowed full floors)
- gebaeudehoeheMax: float (maximum building height in meters)
- laermschutzzone: string (noise protection zone)
- hochwasserschutzzone: string (flood protection zone)
- grundwasserschutzzone: string (groundwater protection zone)
- parzelleBebaut: JaNein enum (is plot built)
- parzelleErschlossen: JaNein enum (is plot developed)
- parzelleHanglage: JaNein enum (is plot on slope)
**Important relationships:**
- Projekte contain Parzellen (projects have plots)
- Parzelle links to Gemeinde (via kontextGemeinde)
- Gemeinde links to Kanton (via id_kanton)
- Kanton links to Land (via id_land)
- Location queries (city, postal code) should use Parzelle.kontextGemeinde (municipality name will be resolved to ID)
- Projekt does NOT have location fields directly - location is stored in associated Parzellen
Return a JSON object with the following structure:
{
"intent": "CREATE|READ|UPDATE|DELETE|QUERY",
"entity": "Projekt|Parzelle|Dokument|Kanton|Gemeinde|null",
"parameters": {
// Extracted parameters from user input
// For CREATE/UPDATE: include all relevant fields using EXACT field names from above
// For READ: include filter criteria using EXACT field names (id, label, plz, kontextGemeinde, etc.)
// For DELETE: include entity ID if mentioned
// For QUERY: include queryText if SQL is detected
// IMPORTANT: Use only field names that exist in the entity definition above
},
"confidence": 0.0-1.0 // Confidence score for the analysis
}
Examples:
- Input: "Erstelle ein neues Projekt namens 'Hauptstrasse 42'"
Output: {"intent": "CREATE", "entity": "Projekt", "parameters": {"label": "Hauptstrasse 42"}, "confidence": 0.95}
- Input: "Zeige mir alle Projekte"
Output: {"intent": "READ", "entity": "Projekt", "parameters": {}, "confidence": 0.9}
- Input: "Zeige mir Projekte in Zürich" or "Wie viele Projekte in Zürich"
Output: {"intent": "READ", "entity": "Projekt", "parameters": {"location_filter": "Zürich"}, "confidence": 0.9}
Note: For project location queries, use Projekt entity with location_filter parameter
- Input: "Zeige mir Parzellen mit PLZ 8000"
Output: {"intent": "READ", "entity": "Parzelle", "parameters": {"plz": "8000"}, "confidence": 0.95}
- Input: "Aktualisiere Projekt XYZ mit Status 'Planung'"
Output: {"intent": "UPDATE", "entity": "Projekt", "parameters": {"id": "XYZ", "statusProzess": "Planung"}, "confidence": 0.85}
- Input: "SELECT * FROM Projekt WHERE label = 'Test'"
Output: {"intent": "QUERY", "entity": null, "parameters": {"queryText": "SELECT * FROM Projekt WHERE label = 'Test'", "queryType": "sql"}, "confidence": 1.0}
- Input: "Lösche Parzelle ABC"
Output: {"intent": "DELETE", "entity": "Parzelle", "parameters": {"id": "ABC"}, "confidence": 0.9}

View file

@ -0,0 +1,17 @@
```json
{
"intent": "READ",
"entity": "Parzelle",
"parameters": {
"kontextGemeinde": "Zürich"
},
"confidence": 0.9
}
```
**Reasoning:**
- The user is asking "wie viele parzellen in zürich gibt es?" (how many plots are there in Zürich?)
- **Intent**: READ - The user wants to query/read information about existing entities
- **Entity**: Parzelle - The user is specifically asking about "parzellen" (plots/parcels)
- **Parameters**: The location "Zürich" refers to a municipality (Gemeinde). Since Parzelle has the field `kontextGemeinde` which links to the municipality, this is the appropriate field to use for filtering by location
- **Confidence**: 0.9 - High confidence as the intent and entity are clearly stated, though the exact count operation is implicit

View file

@ -0,0 +1,89 @@
Analyze the following user command and extract the intent, entity, and parameters.
User Command: "wie viele parzellen in zürich gibt es?"
Available intents:
- CREATE: User wants to create a new entity
- READ: User wants to read/query entities
- UPDATE: User wants to update an existing entity
- DELETE: User wants to delete an entity
- QUERY: User wants to execute a database query (SQL statements)
Available entities and their fields:
**Projekt** (Real estate project):
- id: string (primary key)
- mandateId: string (mandate ID)
- label: string (project designation/name)
- statusProzess: string enum (Eingang, Analyse, Studie, Planung, Baurechtsverfahren, Umsetzung, Archiv)
- perimeter: GeoPolylinie (geographic boundary, JSONB)
- baulinie: GeoPolylinie (building line, JSONB)
- parzellen: List[Parzelle] (plots belonging to project, JSONB)
- dokumente: List[Dokument] (documents, JSONB)
- kontextInformationen: List[Kontext] (context info, JSONB)
**Parzelle** (Plot/parcel):
- id: string (primary key)
- mandateId: string (mandate ID)
- label: string (plot designation)
- strasseNr: string (street and house number)
- plz: string (postal code)
- kontextGemeinde: string (municipality ID, Foreign Key to Gemeinde table)
- bauzone: string (building zone, e.g. W3, WG2)
- az: float (Ausnützungsziffer)
- bz: float (Bebauungsziffer)
- vollgeschossZahl: int (number of allowed full floors)
- gebaeudehoeheMax: float (maximum building height in meters)
- laermschutzzone: string (noise protection zone)
- hochwasserschutzzone: string (flood protection zone)
- grundwasserschutzzone: string (groundwater protection zone)
- parzelleBebaut: JaNein enum (is plot built)
- parzelleErschlossen: JaNein enum (is plot developed)
- parzelleHanglage: JaNein enum (is plot on slope)
**Important relationships:**
- Projekte contain Parzellen (projects have plots)
- Parzelle links to Gemeinde (via kontextGemeinde)
- Gemeinde links to Kanton (via id_kanton)
- Kanton links to Land (via id_land)
- Location queries (city, postal code) should use Parzelle.kontextGemeinde (municipality name will be resolved to ID)
- Projekt does NOT have location fields directly - location is stored in associated Parzellen
Return a JSON object with the following structure:
{
"intent": "CREATE|READ|UPDATE|DELETE|QUERY",
"entity": "Projekt|Parzelle|Dokument|Kanton|Gemeinde|null",
"parameters": {
// Extracted parameters from user input
// For CREATE/UPDATE: include all relevant fields using EXACT field names from above
// For READ: include filter criteria using EXACT field names (id, label, plz, kontextGemeinde, etc.)
// For DELETE: include entity ID if mentioned
// For QUERY: include queryText if SQL is detected
// IMPORTANT: Use only field names that exist in the entity definition above
},
"confidence": 0.0-1.0 // Confidence score for the analysis
}
Examples:
- Input: "Erstelle ein neues Projekt namens 'Hauptstrasse 42'"
Output: {"intent": "CREATE", "entity": "Projekt", "parameters": {"label": "Hauptstrasse 42"}, "confidence": 0.95}
- Input: "Zeige mir alle Projekte"
Output: {"intent": "READ", "entity": "Projekt", "parameters": {}, "confidence": 0.9}
- Input: "Zeige mir Projekte in Zürich" or "Wie viele Projekte in Zürich"
Output: {"intent": "READ", "entity": "Projekt", "parameters": {"location_filter": "Zürich"}, "confidence": 0.9}
Note: For project location queries, use Projekt entity with location_filter parameter
- Input: "Zeige mir Parzellen mit PLZ 8000"
Output: {"intent": "READ", "entity": "Parzelle", "parameters": {"plz": "8000"}, "confidence": 0.95}
- Input: "Aktualisiere Projekt XYZ mit Status 'Planung'"
Output: {"intent": "UPDATE", "entity": "Projekt", "parameters": {"id": "XYZ", "statusProzess": "Planung"}, "confidence": 0.85}
- Input: "SELECT * FROM Projekt WHERE label = 'Test'"
Output: {"intent": "QUERY", "entity": null, "parameters": {"queryText": "SELECT * FROM Projekt WHERE label = 'Test'", "queryType": "sql"}, "confidence": 1.0}
- Input: "Lösche Parzelle ABC"
Output: {"intent": "DELETE", "entity": "Parzelle", "parameters": {"id": "ABC"}, "confidence": 0.9}

View file

@ -0,0 +1,17 @@
```json
{
"intent": "READ",
"entity": "Parzelle",
"parameters": {
"kontextGemeinde": "Zürich"
},
"confidence": 0.9
}
```
**Reasoning:**
- The user is asking "wie viele parzellen in zürich gibt es?" (how many plots are there in Zürich?)
- **Intent**: READ - The user wants to query/read information about existing entities
- **Entity**: Parzelle - The user is specifically asking about "parzellen" (plots/parcels)
- **Parameters**: The location "Zürich" refers to a municipality (Gemeinde). Since Parzelle has the field `kontextGemeinde` which links to the municipality, this is the appropriate field to use for filtering by location
- **Confidence**: 0.9 - High confidence as the intent and entity are clearly stated, though the exact count operation is implicit

View file

@ -0,0 +1,106 @@
Analyze the following user command and extract the intent, entity, and parameters.
User Command: "add a new parzelle with these information into the database: Parzellen-Informationen
Ausgewählte Parzelle
ID:AA1704
Nummer:AA1704
Name:AA1704
EGRID:CH887199917793
IdentND:ZH0200000261
Kanton:ZH
Gemeinde:Zürich
Gemeinde-Code:261
Fläche:6514.99 m²
Zentrum (LV95):2682951.44, 1247622.91
Geoportal:
Link öffnen
Kartenansicht
Zentrum:2682951.44, 1247622.91
Bounds Min:2682914.00, 1247582.00
Bounds Max:2683024.30, 1247667.50"
Available intents:
- CREATE: User wants to create a new entity
- READ: User wants to read/query entities
- UPDATE: User wants to update an existing entity
- DELETE: User wants to delete an entity
- QUERY: User wants to execute a database query (SQL statements)
Available entities and their fields:
**Projekt** (Real estate project):
- id: string (primary key)
- mandateId: string (mandate ID)
- label: string (project designation/name)
- statusProzess: string enum (Eingang, Analyse, Studie, Planung, Baurechtsverfahren, Umsetzung, Archiv)
- perimeter: GeoPolylinie (geographic boundary, JSONB)
- baulinie: GeoPolylinie (building line, JSONB)
- parzellen: List[Parzelle] (plots belonging to project, JSONB)
- dokumente: List[Dokument] (documents, JSONB)
- kontextInformationen: List[Kontext] (context info, JSONB)
**Parzelle** (Plot/parcel):
- id: string (primary key)
- mandateId: string (mandate ID)
- label: string (plot designation)
- strasseNr: string (street and house number)
- plz: string (postal code)
- kontextGemeinde: string (municipality ID, Foreign Key to Gemeinde table)
- bauzone: string (building zone, e.g. W3, WG2)
- az: float (Ausnützungsziffer)
- bz: float (Bebauungsziffer)
- vollgeschossZahl: int (number of allowed full floors)
- gebaeudehoeheMax: float (maximum building height in meters)
- laermschutzzone: string (noise protection zone)
- hochwasserschutzzone: string (flood protection zone)
- grundwasserschutzzone: string (groundwater protection zone)
- parzelleBebaut: JaNein enum (is plot built)
- parzelleErschlossen: JaNein enum (is plot developed)
- parzelleHanglage: JaNein enum (is plot on slope)
**Important relationships:**
- Projekte contain Parzellen (projects have plots)
- Parzelle links to Gemeinde (via kontextGemeinde)
- Gemeinde links to Kanton (via id_kanton)
- Kanton links to Land (via id_land)
- Location queries (city, postal code) should use Parzelle.kontextGemeinde (municipality name will be resolved to ID)
- Projekt does NOT have location fields directly - location is stored in associated Parzellen
Return a JSON object with the following structure:
{
"intent": "CREATE|READ|UPDATE|DELETE|QUERY",
"entity": "Projekt|Parzelle|Dokument|Kanton|Gemeinde|null",
"parameters": {
// Extracted parameters from user input
// For CREATE/UPDATE: include all relevant fields using EXACT field names from above
// For READ: include filter criteria using EXACT field names (id, label, plz, kontextGemeinde, etc.)
// For DELETE: include entity ID if mentioned
// For QUERY: include queryText if SQL is detected
// IMPORTANT: Use only field names that exist in the entity definition above
},
"confidence": 0.0-1.0 // Confidence score for the analysis
}
Examples:
- Input: "Erstelle ein neues Projekt namens 'Hauptstrasse 42'"
Output: {"intent": "CREATE", "entity": "Projekt", "parameters": {"label": "Hauptstrasse 42"}, "confidence": 0.95}
- Input: "Zeige mir alle Projekte"
Output: {"intent": "READ", "entity": "Projekt", "parameters": {}, "confidence": 0.9}
- Input: "Zeige mir Projekte in Zürich" or "Wie viele Projekte in Zürich"
Output: {"intent": "READ", "entity": "Projekt", "parameters": {"location_filter": "Zürich"}, "confidence": 0.9}
Note: For project location queries, use Projekt entity with location_filter parameter
- Input: "Zeige mir Parzellen mit PLZ 8000"
Output: {"intent": "READ", "entity": "Parzelle", "parameters": {"plz": "8000"}, "confidence": 0.95}
- Input: "Aktualisiere Projekt XYZ mit Status 'Planung'"
Output: {"intent": "UPDATE", "entity": "Projekt", "parameters": {"id": "XYZ", "statusProzess": "Planung"}, "confidence": 0.85}
- Input: "SELECT * FROM Projekt WHERE label = 'Test'"
Output: {"intent": "QUERY", "entity": null, "parameters": {"queryText": "SELECT * FROM Projekt WHERE label = 'Test'", "queryType": "sql"}, "confidence": 1.0}
- Input: "Lösche Parzelle ABC"
Output: {"intent": "DELETE", "entity": "Parzelle", "parameters": {"id": "ABC"}, "confidence": 0.9}

View file

@ -0,0 +1,37 @@
```json
{
"intent": "CREATE",
"entity": "Parzelle",
"parameters": {
"id": "AA1704",
"label": "AA1704",
"kontextGemeinde": "Zürich"
},
"confidence": 0.75
}
```
**Analysis:**
The user wants to add a new "Parzelle" (plot/parcel) to the database. The command provides extensive information about the parcel, but only a subset can be mapped to the available fields in the **Parzelle** entity definition:
**Mapped fields:**
- `id`: "AA1704" (from ID/Nummer)
- `label`: "AA1704" (from Name)
- `kontextGemeinde`: "Zürich" (from Gemeinde - will need to be resolved to municipality ID)
**Unmapped information** (not available in the Parzelle entity schema):
- EGRID: CH887199917793
- IdentND: ZH0200000261
- Kanton: ZH
- Gemeinde-Code: 261
- Fläche: 6514.99 m²
- Zentrum coordinates (LV95): 2682951.44, 1247622.91
- Bounds coordinates
**Confidence reasoning:**
The confidence is set to 0.75 because:
- The intent (CREATE) is clear
- The entity (Parzelle) is explicitly mentioned
- However, most of the provided information cannot be stored in the current Parzelle schema
- The user may expect all this data to be stored, but the system can only capture id, label, and kontextGemeinde from the provided information

View file

@ -0,0 +1,131 @@
Analyze the following user command and extract the intent, entity, and parameters.
User Command: "erstelle einen neuen parzelleneintrag mit diesen informationen: ID:AA4198
Nummer:AA4198
Name:AA4198
EGRID:CH879177719964
IdentND:ZH0200000261
Adresse:Steinmühleplatz 3, 8001 Zürich
Kanton:ZH
Gemeinde:Zürich
Gemeinde-Code:261
Fläche:1972.83 m²
Zentrum (LV95):2682910.35, 1247566.80"
Available intents:
- CREATE: User wants to create a new entity
- READ: User wants to read/query entities
- UPDATE: User wants to update an existing entity
- DELETE: User wants to delete an entity
- QUERY: User wants to execute a database query (SQL statements)
Available entities and their fields:
**Projekt** (Real estate project):
- id: string (primary key)
- mandateId: string (mandate ID)
- label: string (project designation/name)
- statusProzess: string enum (Eingang, Analyse, Studie, Planung, Baurechtsverfahren, Umsetzung, Archiv)
- perimeter: GeoPolylinie (geographic boundary, JSONB)
- baulinie: GeoPolylinie (building line, JSONB)
- parzellen: List[Parzelle] (plots belonging to project, JSONB)
- dokumente: List[Dokument] (documents, JSONB)
- kontextInformationen: List[Kontext] (context info, JSONB)
**Parzelle** (Plot/parcel):
- id: string (primary key)
- mandateId: string (mandate ID)
- label: string (plot designation)
- strasseNr: string (street and house number)
- plz: string (postal code)
- kontextGemeinde: string (municipality ID, Foreign Key to Gemeinde table)
- bauzone: string (building zone, e.g. W3, WG2)
- az: float (Ausnützungsziffer)
- bz: float (Bebauungsziffer)
- vollgeschossZahl: int (number of allowed full floors)
- gebaeudehoeheMax: float (maximum building height in meters)
- laermschutzzone: string (noise protection zone)
- hochwasserschutzzone: string (flood protection zone)
- grundwasserschutzzone: string (groundwater protection zone)
- parzelleBebaut: JaNein enum (is plot built)
- parzelleErschlossen: JaNein enum (is plot developed)
- parzelleHanglage: JaNein enum (is plot on slope)
**Important relationships:**
- Projekte contain Parzellen (projects have plots)
- Parzelle links to Gemeinde (via kontextGemeinde)
- Gemeinde links to Kanton (via id_kanton)
- Kanton links to Land (via id_land)
- Location queries (city, postal code) should use Parzelle.kontextGemeinde (municipality name will be resolved to ID)
- Projekt does NOT have location fields directly - location is stored in associated Parzellen
Return a JSON object with the following structure:
{
"intent": "CREATE|READ|UPDATE|DELETE|QUERY",
"entity": "Projekt|Parzelle|Dokument|Kanton|Gemeinde|null",
"parameters": {
// Extracted parameters from user input
// For CREATE/UPDATE: include all relevant fields using EXACT field names from above
// For READ: include filter criteria using EXACT field names (id, label, plz, kontextGemeinde, etc.)
// For DELETE: include entity ID if mentioned
// For QUERY: include queryText if SQL is detected
// IMPORTANT: Use only field names that exist in the entity definition above
},
"confidence": 0.0-1.0 // Confidence score for the analysis
}
Examples:
- Input: "Erstelle ein neues Projekt namens 'Hauptstrasse 42'"
Output: {"intent": "CREATE", "entity": "Projekt", "parameters": {"label": "Hauptstrasse 42"}, "confidence": 0.95}
- Input: "Erstelle eine Parzelle mit Label 123, PLZ 8000, Gemeinde Zürich, Bauzone W3"
Output: {"intent": "CREATE", "entity": "Parzelle", "parameters": {"label": "123", "plz": "8000", "kontextGemeinde": "Zürich", "bauzone": "W3"}, "confidence": 0.95}
- Input: "Parzellen-Informationen: ID:AA1704, Nummer:AA1704, EGRID:CH887199917793, Kanton:ZH, Gemeinde:Zürich, Gemeinde-Code:261, Fläche:6514.99 m², Zentrum:2682951.44,1247622.91"
Output: {
"intent": "CREATE",
"entity": "Parzelle",
"parameters": {
"label": "AA1704",
"parzellenAliasTags": ["AA1704"],
"kontextGemeinde": "Zürich",
"kontextInformationen": [
{"kategorie": "Swiss Topo", "schluessel": "EGRID", "wert": "CH887199917793"},
{"kategorie": "Kanton", "schluessel": "Abkürzung", "wert": "ZH"},
{"kategorie": "Gemeinde", "schluessel": "BFS-Nummer", "wert": "261"},
{"kategorie": "Parzelle", "schluessel": "Fläche", "wert": "6514.99", "einheit": "m²"},
{"kategorie": "Parzelle", "schluessel": "Zentrum_X", "wert": "2682951.44", "crs": "EPSG:2056"},
{"kategorie": "Parzelle", "schluessel": "Zentrum_Y", "wert": "1247622.91", "crs": "EPSG:2056"}
]
},
"confidence": 0.9
}
Note: Extract structured data from detailed input. Use kontextInformationen for metadata like EGRID, coordinates, area, etc.
- Input: "Zeige mir alle Projekte"
Output: {"intent": "READ", "entity": "Projekt", "parameters": {}, "confidence": 0.9}
- Input: "Zeige mir Projekte in Zürich" or "Wie viele Projekte in Zürich"
Output: {"intent": "READ", "entity": "Projekt", "parameters": {"location_filter": "Zürich"}, "confidence": 0.9}
Note: For project location queries, use Projekt entity with location_filter parameter
- Input: "Zeige mir Parzellen mit PLZ 8000"
Output: {"intent": "READ", "entity": "Parzelle", "parameters": {"plz": "8000"}, "confidence": 0.95}
- Input: "Aktualisiere Projekt XYZ mit Status 'Planung'"
Output: {"intent": "UPDATE", "entity": "Projekt", "parameters": {"id": "XYZ", "statusProzess": "Planung"}, "confidence": 0.85}
- Input: "SELECT * FROM Projekt WHERE label = 'Test'"
Output: {"intent": "QUERY", "entity": null, "parameters": {"queryText": "SELECT * FROM Projekt WHERE label = 'Test'", "queryType": "sql"}, "confidence": 1.0}
- Input: "Lösche Parzelle ABC"
Output: {"intent": "DELETE", "entity": "Parzelle", "parameters": {"id": "ABC"}, "confidence": 0.9}
IMPORTANT EXTRACTION RULES:
1. For CREATE operations, extract ALL mentioned data fields from the user input
2. Use kontextInformationen array for metadata that doesn't have dedicated fields (EGRID, BFS numbers, area, coordinates, etc.)
3. Match field names EXACTLY to the entity definition above
4. Convert data types correctly (strings for text, numbers for numeric values)
5. Extract coordinates, areas, and other numeric values from text
6. When multiple values are mentioned for the same concept (ID, Nummer, Name), use the most relevant one for 'label' and put alternatives in parzellenAliasTags

View file

@ -0,0 +1,63 @@
```json
{
"intent": "CREATE",
"entity": "Parzelle",
"parameters": {
"label": "AA4198",
"strasseNr": "Steinmühleplatz 3",
"plz": "8001",
"kontextGemeinde": "Zürich",
"kontextInformationen": [
{
"kategorie": "Parzelle",
"schluessel": "ID",
"wert": "AA4198"
},
{
"kategorie": "Parzelle",
"schluessel": "Nummer",
"wert": "AA4198"
},
{
"kategorie": "Swiss Topo",
"schluessel": "EGRID",
"wert": "CH879177719964"
},
{
"kategorie": "Parzelle",
"schluessel": "IdentND",
"wert": "ZH0200000261"
},
{
"kategorie": "Kanton",
"schluessel": "Abkürzung",
"wert": "ZH"
},
{
"kategorie": "Gemeinde",
"schluessel": "BFS-Nummer",
"wert": "261"
},
{
"kategorie": "Parzelle",
"schluessel": "Fläche",
"wert": "1972.83",
"einheit": "m²"
},
{
"kategorie": "Parzelle",
"schluessel": "Zentrum_X",
"wert": "2682910.35",
"crs": "EPSG:2056"
},
{
"kategorie": "Parzelle",
"schluessel": "Zentrum_Y",
"wert": "1247566.80",
"crs": "EPSG:2056"
}
]
},
"confidence": 0.95
}
```

View file

@ -0,0 +1,131 @@
Analyze the following user command and extract the intent, entity, and parameters.
User Command: "erstelle einen neuen parzelleneintrag mit diesen informationen: ID:AA4198
Nummer:AA4198
Name:AA4198
EGRID:CH879177719964
IdentND:ZH0200000261
Adresse:Steinmühleplatz 3, 8001 Zürich
Kanton:ZH
Gemeinde:Zürich
Gemeinde-Code:261
Fläche:1972.83 m²
Zentrum (LV95):2682910.35, 1247566.80"
Available intents:
- CREATE: User wants to create a new entity
- READ: User wants to read/query entities
- UPDATE: User wants to update an existing entity
- DELETE: User wants to delete an entity
- QUERY: User wants to execute a database query (SQL statements)
Available entities and their fields:
**Projekt** (Real estate project):
- id: string (primary key)
- mandateId: string (mandate ID)
- label: string (project designation/name)
- statusProzess: string enum (Eingang, Analyse, Studie, Planung, Baurechtsverfahren, Umsetzung, Archiv)
- perimeter: GeoPolylinie (geographic boundary, JSONB)
- baulinie: GeoPolylinie (building line, JSONB)
- parzellen: List[Parzelle] (plots belonging to project, JSONB)
- dokumente: List[Dokument] (documents, JSONB)
- kontextInformationen: List[Kontext] (context info, JSONB)
**Parzelle** (Plot/parcel):
- id: string (primary key)
- mandateId: string (mandate ID)
- label: string (plot designation)
- strasseNr: string (street and house number)
- plz: string (postal code)
- kontextGemeinde: string (municipality ID, Foreign Key to Gemeinde table)
- bauzone: string (building zone, e.g. W3, WG2)
- az: float (Ausnützungsziffer)
- bz: float (Bebauungsziffer)
- vollgeschossZahl: int (number of allowed full floors)
- gebaeudehoeheMax: float (maximum building height in meters)
- laermschutzzone: string (noise protection zone)
- hochwasserschutzzone: string (flood protection zone)
- grundwasserschutzzone: string (groundwater protection zone)
- parzelleBebaut: JaNein enum (is plot built)
- parzelleErschlossen: JaNein enum (is plot developed)
- parzelleHanglage: JaNein enum (is plot on slope)
**Important relationships:**
- Projekte contain Parzellen (projects have plots)
- Parzelle links to Gemeinde (via kontextGemeinde)
- Gemeinde links to Kanton (via id_kanton)
- Kanton links to Land (via id_land)
- Location queries (city, postal code) should use Parzelle.kontextGemeinde (municipality name will be resolved to ID)
- Projekt does NOT have location fields directly - location is stored in associated Parzellen
Return a JSON object with the following structure:
{
"intent": "CREATE|READ|UPDATE|DELETE|QUERY",
"entity": "Projekt|Parzelle|Dokument|Kanton|Gemeinde|null",
"parameters": {
// Extracted parameters from user input
// For CREATE/UPDATE: include all relevant fields using EXACT field names from above
// For READ: include filter criteria using EXACT field names (id, label, plz, kontextGemeinde, etc.)
// For DELETE: include entity ID if mentioned
// For QUERY: include queryText if SQL is detected
// IMPORTANT: Use only field names that exist in the entity definition above
},
"confidence": 0.0-1.0 // Confidence score for the analysis
}
Examples:
- Input: "Erstelle ein neues Projekt namens 'Hauptstrasse 42'"
Output: {"intent": "CREATE", "entity": "Projekt", "parameters": {"label": "Hauptstrasse 42"}, "confidence": 0.95}
- Input: "Erstelle eine Parzelle mit Label 123, PLZ 8000, Gemeinde Zürich, Bauzone W3"
Output: {"intent": "CREATE", "entity": "Parzelle", "parameters": {"label": "123", "plz": "8000", "kontextGemeinde": "Zürich", "bauzone": "W3"}, "confidence": 0.95}
- Input: "Parzellen-Informationen: ID:AA1704, Nummer:AA1704, EGRID:CH887199917793, Kanton:ZH, Gemeinde:Zürich, Gemeinde-Code:261, Fläche:6514.99 m², Zentrum:2682951.44,1247622.91"
Output: {
"intent": "CREATE",
"entity": "Parzelle",
"parameters": {
"label": "AA1704",
"parzellenAliasTags": ["AA1704"],
"kontextGemeinde": "Zürich",
"kontextInformationen": [
{"kategorie": "Swiss Topo", "schluessel": "EGRID", "wert": "CH887199917793"},
{"kategorie": "Kanton", "schluessel": "Abkürzung", "wert": "ZH"},
{"kategorie": "Gemeinde", "schluessel": "BFS-Nummer", "wert": "261"},
{"kategorie": "Parzelle", "schluessel": "Fläche", "wert": "6514.99", "einheit": "m²"},
{"kategorie": "Parzelle", "schluessel": "Zentrum_X", "wert": "2682951.44", "crs": "EPSG:2056"},
{"kategorie": "Parzelle", "schluessel": "Zentrum_Y", "wert": "1247622.91", "crs": "EPSG:2056"}
]
},
"confidence": 0.9
}
Note: Extract structured data from detailed input. Use kontextInformationen for metadata like EGRID, coordinates, area, etc.
- Input: "Zeige mir alle Projekte"
Output: {"intent": "READ", "entity": "Projekt", "parameters": {}, "confidence": 0.9}
- Input: "Zeige mir Projekte in Zürich" or "Wie viele Projekte in Zürich"
Output: {"intent": "READ", "entity": "Projekt", "parameters": {"location_filter": "Zürich"}, "confidence": 0.9}
Note: For project location queries, use Projekt entity with location_filter parameter
- Input: "Zeige mir Parzellen mit PLZ 8000"
Output: {"intent": "READ", "entity": "Parzelle", "parameters": {"plz": "8000"}, "confidence": 0.95}
- Input: "Aktualisiere Projekt XYZ mit Status 'Planung'"
Output: {"intent": "UPDATE", "entity": "Projekt", "parameters": {"id": "XYZ", "statusProzess": "Planung"}, "confidence": 0.85}
- Input: "SELECT * FROM Projekt WHERE label = 'Test'"
Output: {"intent": "QUERY", "entity": null, "parameters": {"queryText": "SELECT * FROM Projekt WHERE label = 'Test'", "queryType": "sql"}, "confidence": 1.0}
- Input: "Lösche Parzelle ABC"
Output: {"intent": "DELETE", "entity": "Parzelle", "parameters": {"id": "ABC"}, "confidence": 0.9}
IMPORTANT EXTRACTION RULES:
1. For CREATE operations, extract ALL mentioned data fields from the user input
2. Use kontextInformationen array for metadata that doesn't have dedicated fields (EGRID, BFS numbers, area, coordinates, etc.)
3. Match field names EXACTLY to the entity definition above
4. Convert data types correctly (strings for text, numbers for numeric values)
5. Extract coordinates, areas, and other numeric values from text
6. When multiple values are mentioned for the same concept (ID, Nummer, Name), use the most relevant one for 'label' and put alternatives in parzellenAliasTags

View file

@ -0,0 +1,63 @@
```json
{
"intent": "CREATE",
"entity": "Parzelle",
"parameters": {
"label": "AA4198",
"strasseNr": "Steinmühleplatz 3",
"plz": "8001",
"kontextGemeinde": "Zürich",
"kontextInformationen": [
{
"kategorie": "Parzelle",
"schluessel": "ID",
"wert": "AA4198"
},
{
"kategorie": "Parzelle",
"schluessel": "Nummer",
"wert": "AA4198"
},
{
"kategorie": "Swiss Topo",
"schluessel": "EGRID",
"wert": "CH879177719964"
},
{
"kategorie": "Parzelle",
"schluessel": "IdentND",
"wert": "ZH0200000261"
},
{
"kategorie": "Kanton",
"schluessel": "Abkürzung",
"wert": "ZH"
},
{
"kategorie": "Gemeinde",
"schluessel": "BFS-Nummer",
"wert": "261"
},
{
"kategorie": "Parzelle",
"schluessel": "Fläche",
"wert": "1972.83",
"einheit": "m²"
},
{
"kategorie": "Parzelle",
"schluessel": "Zentrum_X",
"wert": "2682910.35",
"crs": "EPSG:2056"
},
{
"kategorie": "Parzelle",
"schluessel": "Zentrum_Y",
"wert": "1247566.80",
"crs": "EPSG:2056"
}
]
},
"confidence": 0.95
}
```

View file

@ -0,0 +1,137 @@
Analyze the following user command and extract the intent, entity, and parameters.
User Command: "erstelle einen neuen parzelleneintrag mit diesen informationen: ID:AA4198
Nummer:AA4198
Name:AA4198
EGRID:CH879177719964
IdentND:ZH0200000261
Adresse:Steinmühleplatz 3, 8001 Zürich
Kanton:ZH
Gemeinde:Zürich
Gemeinde-Code:261
Fläche:1972.83 m²
Zentrum (LV95):2682910.35, 1247566.80"
Available intents:
- CREATE: User wants to create a new entity
- READ: User wants to read/query entities
- UPDATE: User wants to update an existing entity
- DELETE: User wants to delete an entity
- QUERY: User wants to execute a database query (SQL statements)
Available entities and their fields:
**Projekt** (Real estate project):
- id: string (primary key)
- mandateId: string (mandate ID)
- label: string (project designation/name)
- statusProzess: string enum (Eingang, Analyse, Studie, Planung, Baurechtsverfahren, Umsetzung, Archiv)
- perimeter: GeoPolylinie (geographic boundary, JSONB)
- baulinie: GeoPolylinie (building line, JSONB)
- parzellen: List[Parzelle] (plots belonging to project, JSONB)
- dokumente: List[Dokument] (documents, JSONB)
- kontextInformationen: List[Kontext] (context info, JSONB)
**Parzelle** (Plot/parcel):
- id: string (primary key)
- mandateId: string (mandate ID)
- label: string (plot designation)
- strasseNr: string (street and house number)
- plz: string (postal code)
- kontextGemeinde: string (municipality ID, Foreign Key to Gemeinde table)
- bauzone: string (building zone, e.g. W3, WG2)
- az: float (Ausnützungsziffer)
- bz: float (Bebauungsziffer)
- vollgeschossZahl: int (number of allowed full floors)
- gebaeudehoeheMax: float (maximum building height in meters)
- laermschutzzone: string (noise protection zone)
- hochwasserschutzzone: string (flood protection zone)
- grundwasserschutzzone: string (groundwater protection zone)
- parzelleBebaut: JaNein enum (is plot built)
- parzelleErschlossen: JaNein enum (is plot developed)
- parzelleHanglage: JaNein enum (is plot on slope)
- kontextInformationen: List[Kontext] (metadata - each item has 'thema' and 'inhalt' fields only)
**Kontext** (Context information for metadata):
- thema: string (topic/subject, e.g. "EGRID", "Fläche", "Zentrum")
- inhalt: string (content as text, e.g. "CH887199917793", "6514.99 m²", "X: 123, Y: 456")
**Important relationships:**
- Projekte contain Parzellen (projects have plots)
- Parzelle links to Gemeinde (via kontextGemeinde)
- Gemeinde links to Kanton (via id_kanton)
- Kanton links to Land (via id_land)
- Location queries (city, postal code) should use Parzelle.kontextGemeinde (municipality name will be resolved to ID)
- Projekt does NOT have location fields directly - location is stored in associated Parzellen
Return a JSON object with the following structure:
{
"intent": "CREATE|READ|UPDATE|DELETE|QUERY",
"entity": "Projekt|Parzelle|Dokument|Kanton|Gemeinde|null",
"parameters": {
// Extracted parameters from user input
// For CREATE/UPDATE: include all relevant fields using EXACT field names from above
// For READ: include filter criteria using EXACT field names (id, label, plz, kontextGemeinde, etc.)
// For DELETE: include entity ID if mentioned
// For QUERY: include queryText if SQL is detected
// IMPORTANT: Use only field names that exist in the entity definition above
},
"confidence": 0.0-1.0 // Confidence score for the analysis
}
Examples:
- Input: "Erstelle ein neues Projekt namens 'Hauptstrasse 42'"
Output: {"intent": "CREATE", "entity": "Projekt", "parameters": {"label": "Hauptstrasse 42"}, "confidence": 0.95}
- Input: "Erstelle eine Parzelle mit Label 123, PLZ 8000, Gemeinde Zürich, Bauzone W3"
Output: {"intent": "CREATE", "entity": "Parzelle", "parameters": {"label": "123", "plz": "8000", "kontextGemeinde": "Zürich", "bauzone": "W3"}, "confidence": 0.95}
- Input: "Parzellen-Informationen: ID:AA1704, Nummer:AA1704, EGRID:CH887199917793, Kanton:ZH, Gemeinde:Zürich, Gemeinde-Code:261, Fläche:6514.99 m², Zentrum:2682951.44,1247622.91"
Output: {
"intent": "CREATE",
"entity": "Parzelle",
"parameters": {
"label": "AA1704",
"parzellenAliasTags": ["AA1704"],
"kontextGemeinde": "Zürich",
"kontextInformationen": [
{"thema": "EGRID", "inhalt": "CH887199917793"},
{"thema": "Kanton", "inhalt": "ZH"},
{"thema": "BFS-Nummer", "inhalt": "261"},
{"thema": "Fläche", "inhalt": "6514.99 m²"},
{"thema": "Zentrum (LV95)", "inhalt": "X: 2682951.44 m, Y: 1247622.91 m (EPSG:2056)"}
]
},
"confidence": 0.9
}
Note: Extract structured data from detailed input. Use kontextInformationen for metadata. Each item has 'thema' (topic) and 'inhalt' (content as text).
- Input: "Zeige mir alle Projekte"
Output: {"intent": "READ", "entity": "Projekt", "parameters": {}, "confidence": 0.9}
- Input: "Zeige mir Projekte in Zürich" or "Wie viele Projekte in Zürich"
Output: {"intent": "READ", "entity": "Projekt", "parameters": {"location_filter": "Zürich"}, "confidence": 0.9}
Note: For project location queries, use Projekt entity with location_filter parameter
- Input: "Zeige mir Parzellen mit PLZ 8000"
Output: {"intent": "READ", "entity": "Parzelle", "parameters": {"plz": "8000"}, "confidence": 0.95}
- Input: "Aktualisiere Projekt XYZ mit Status 'Planung'"
Output: {"intent": "UPDATE", "entity": "Projekt", "parameters": {"id": "XYZ", "statusProzess": "Planung"}, "confidence": 0.85}
- Input: "SELECT * FROM Projekt WHERE label = 'Test'"
Output: {"intent": "QUERY", "entity": null, "parameters": {"queryText": "SELECT * FROM Projekt WHERE label = 'Test'", "queryType": "sql"}, "confidence": 1.0}
- Input: "Lösche Parzelle ABC"
Output: {"intent": "DELETE", "entity": "Parzelle", "parameters": {"id": "ABC"}, "confidence": 0.9}
IMPORTANT EXTRACTION RULES:
1. For CREATE operations, extract ALL mentioned data fields from the user input
2. Use kontextInformationen array for metadata that doesn't have dedicated fields (EGRID, BFS numbers, area, coordinates, etc.)
3. Each kontextInformationen item MUST have exactly two fields: 'thema' (topic/subject) and 'inhalt' (content as text string)
4. Format kontextInformationen values as readable text strings, including units (e.g., "6514.99 m²", "X: 123, Y: 456")
5. Match field names EXACTLY to the entity definition above
6. Convert data types correctly (strings for text, numbers for numeric values)
7. Extract coordinates, areas, and other numeric values from text
8. When multiple values are mentioned for the same concept (ID, Nummer, Name), use the most relevant one for 'label' and put alternatives in parzellenAliasTags

View file

@ -0,0 +1,47 @@
```json
{
"intent": "CREATE",
"entity": "Parzelle",
"parameters": {
"label": "AA4198",
"strasseNr": "Steinmühleplatz 3",
"plz": "8001",
"kontextGemeinde": "Zürich",
"kontextInformationen": [
{
"thema": "ID",
"inhalt": "AA4198"
},
{
"thema": "Nummer",
"inhalt": "AA4198"
},
{
"thema": "EGRID",
"inhalt": "CH879177719964"
},
{
"thema": "IdentND",
"inhalt": "ZH0200000261"
},
{
"thema": "Kanton",
"inhalt": "ZH"
},
{
"thema": "BFS-Nummer",
"inhalt": "261"
},
{
"thema": "Fläche",
"inhalt": "1972.83 m²"
},
{
"thema": "Zentrum (LV95)",
"inhalt": "X: 2682910.35 m, Y: 1247566.80 m (EPSG:2056)"
}
]
},
"confidence": 0.95
}
```

View file

@ -6,7 +6,7 @@ Stateless implementation without session management.
import logging
import json
from typing import Optional, Dict, Any
from typing import Optional, Dict, Any, List
from modules.datamodels.datamodelUam import User
from modules.datamodels.datamodelRealEstate import (
Projekt,
@ -72,6 +72,138 @@ async def executeDirectQuery(
# ===== AI-basierte Intent-Erkennung und CRUD-Operationen =====
def _formatEntitySummary(entity_type: str, items: List[Dict[str, Any]], filters: Dict[str, Any]) -> str:
"""
Format a human-readable summary of query results.
Args:
entity_type: Type of entity (Projekt, Parzelle, etc.)
items: List of entity data dictionaries
filters: Filter parameters used in the query
Returns:
Human-readable summary string
"""
if not items:
return f"Keine {entity_type} gefunden"
count = len(items)
filter_desc = ""
if filters:
# Format filter description
if "kontextGemeinde" in filters:
filter_desc = f" in {filters['kontextGemeinde']}"
elif "plz" in filters:
filter_desc = f" mit PLZ {filters['plz']}"
elif "location_filter" in filters:
filter_desc = f" in {filters['location_filter']}"
# Start with count
summary = f"Gefunden: {count} {entity_type}{filter_desc}"
# Add details based on entity type
if entity_type == "Parzelle":
summary += "\n\nDetails:"
for i, item in enumerate(items[:10], 1): # Limit to first 10
parts = []
# Add label or ID
if item.get("label"):
parts.append(f"Parzelle '{item['label']}'")
elif item.get("id"):
parts.append(f"Parzelle {item['id'][:8]}...")
# Add address
if item.get("strasseNr"):
parts.append(item["strasseNr"])
# Add PLZ and municipality
location_parts = []
if item.get("plz"):
location_parts.append(item["plz"])
if item.get("kontextGemeinde"):
location_parts.append(item["kontextGemeinde"])
if location_parts:
parts.append(" ".join(location_parts))
# Add building zone
if item.get("bauzone"):
parts.append(f"Bauzone: {item['bauzone']}")
summary += f"\n{i}. {', '.join(parts)}"
if count > 10:
summary += f"\n... und {count - 10} weitere"
elif entity_type == "Projekt":
summary += "\n\nDetails:"
for i, item in enumerate(items[:10], 1):
parts = []
# Add label
if item.get("label"):
parts.append(f"'{item['label']}'")
# Add status
if item.get("statusProzess"):
parts.append(f"Status: {item['statusProzess']}")
# Add parcel count
parzellen = item.get("parzellen", [])
if parzellen:
parts.append(f"{len(parzellen)} Parzelle(n)")
summary += f"\n{i}. {' - '.join(parts)}"
if count > 10:
summary += f"\n... und {count - 10} weitere"
elif entity_type == "Gemeinde":
summary += "\n\nDetails:"
for i, item in enumerate(items[:10], 1):
parts = []
if item.get("label"):
parts.append(item["label"])
if item.get("plz"):
parts.append(f"PLZ: {item['plz']}")
if item.get("abk"):
parts.append(f"Abk: {item['abk']}")
summary += f"\n{i}. {', '.join(parts)}"
if count > 10:
summary += f"\n... und {count - 10} weitere"
elif entity_type == "Dokument":
summary += "\n\nDetails:"
for i, item in enumerate(items[:10], 1):
parts = []
if item.get("label"):
parts.append(item["label"])
if item.get("dokumentTyp"):
parts.append(f"Typ: {item['dokumentTyp']}")
if item.get("quelle"):
parts.append(f"Quelle: {item['quelle']}")
summary += f"\n{i}. {', '.join(parts)}"
if count > 10:
summary += f"\n... und {count - 10} weitere"
else:
# Generic format for other entity types
if count <= 5:
summary += "\n\nDetails:"
for i, item in enumerate(items, 1):
label = item.get("label") or item.get("id", "")
if label:
summary += f"\n{i}. {label}"
return summary
async def processNaturalLanguageCommand(
currentUser: User,
userInput: str,
@ -117,13 +249,82 @@ async def processNaturalLanguageCommand(
parameters=intentAnalysis.get("parameters", {}),
)
return {
# Build user-friendly response
response = {
"success": True,
"intent": intentAnalysis["intent"],
"entity": intentAnalysis.get("entity"),
"result": result,
}
# Add human-readable summary for operations
if intentAnalysis["intent"] == "CREATE" and isinstance(result, dict):
# Add confirmation message for CREATE operations
operation_result = result.get("result")
if isinstance(operation_result, dict):
entity_name = intentAnalysis.get('entity', 'Eintrag')
label = operation_result.get("label", operation_result.get("id", ""))
# Build detailed message
msg_parts = [f"{entity_name} '{label}' erfolgreich erstellt"]
if entity_name == "Parzelle":
if operation_result.get("plz"):
msg_parts.append(f"PLZ: {operation_result['plz']}")
if operation_result.get("kontextGemeinde"):
msg_parts.append(f"Gemeinde: {operation_result['kontextGemeinde']}")
if operation_result.get("bauzone"):
msg_parts.append(f"Bauzone: {operation_result['bauzone']}")
kontext_items = operation_result.get("kontextInformationen", [])
if kontext_items:
msg_parts.append(f"\n📋 {len(kontext_items)} Kontextinformationen gespeichert:")
for kontext in kontext_items[:5]: # Show first 5
thema = kontext.get("thema", "")
inhalt = kontext.get("inhalt", "")
if thema and inhalt:
msg_parts.append(f"{thema}: {inhalt}")
if len(kontext_items) > 5:
msg_parts.append(f" • ... und {len(kontext_items) - 5} weitere")
elif entity_name == "Projekt":
if operation_result.get("statusProzess"):
msg_parts.append(f"Status: {operation_result['statusProzess']}")
parzellen = operation_result.get("parzellen", [])
if parzellen:
msg_parts.append(f"{len(parzellen)} Parzelle(n)")
response["message"] = "\n".join(msg_parts)
elif intentAnalysis["intent"] == "READ" and isinstance(result, dict):
operation_result = result.get("result")
if isinstance(operation_result, list):
response["count"] = len(operation_result)
entity_name = intentAnalysis.get('entity', 'Einträge')
if len(operation_result) == 0:
# Provide helpful message for empty results
filter_info = intentAnalysis.get('parameters', {})
if filter_info:
filter_desc = ", ".join([f"{k}={v}" for k, v in filter_info.items()])
response["message"] = f"Keine {entity_name} gefunden mit Filter: {filter_desc}. Möglicherweise sind noch keine Daten vorhanden oder der Filter ist zu spezifisch."
else:
response["message"] = f"Keine {entity_name} vorhanden. Erstellen Sie zuerst neue Einträge."
else:
# Create detailed summary based on entity type
response["message"] = _formatEntitySummary(
entity_name,
operation_result,
intentAnalysis.get('parameters', {})
)
elif isinstance(operation_result, dict):
response["count"] = 1
# Format single entity
entity_name = intentAnalysis.get('entity', 'Eintrag')
response["message"] = _formatEntitySummary(entity_name, [operation_result], {})
return response
except Exception as e:
logger.error(f"Error processing natural language command: {str(e)}", exc_info=True)
raise
@ -187,6 +388,11 @@ Available entities and their fields:
- parzelleBebaut: JaNein enum (is plot built)
- parzelleErschlossen: JaNein enum (is plot developed)
- parzelleHanglage: JaNein enum (is plot on slope)
- kontextInformationen: List[Kontext] (metadata - each item has 'thema' and 'inhalt' fields only)
**Kontext** (Context information for metadata):
- thema: string (topic/subject, e.g. "EGRID", "Fläche", "Zentrum")
- inhalt: string (content as text, e.g. "CH887199917793", "6514.99 m²", "X: 123, Y: 456")
**Important relationships:**
- Projekte contain Parzellen (projects have plots)
@ -215,12 +421,35 @@ Examples:
- Input: "Erstelle ein neues Projekt namens 'Hauptstrasse 42'"
Output: {{"intent": "CREATE", "entity": "Projekt", "parameters": {{"label": "Hauptstrasse 42"}}, "confidence": 0.95}}
- Input: "Erstelle eine Parzelle mit Label 123, PLZ 8000, Gemeinde Zürich, Bauzone W3"
Output: {{"intent": "CREATE", "entity": "Parzelle", "parameters": {{"label": "123", "plz": "8000", "kontextGemeinde": "Zürich", "bauzone": "W3"}}, "confidence": 0.95}}
- Input: "Parzellen-Informationen: ID:AA1704, Nummer:AA1704, EGRID:CH887199917793, Kanton:ZH, Gemeinde:Zürich, Gemeinde-Code:261, Fläche:6514.99 m², Zentrum:2682951.44,1247622.91"
Output: {{
"intent": "CREATE",
"entity": "Parzelle",
"parameters": {{
"label": "AA1704",
"parzellenAliasTags": ["AA1704"],
"kontextGemeinde": "Zürich",
"kontextInformationen": [
{{"thema": "EGRID", "inhalt": "CH887199917793"}},
{{"thema": "Kanton", "inhalt": "ZH"}},
{{"thema": "BFS-Nummer", "inhalt": "261"}},
{{"thema": "Fläche", "inhalt": "6514.99 m²"}},
{{"thema": "Zentrum (LV95)", "inhalt": "X: 2682951.44 m, Y: 1247622.91 m (EPSG:2056)"}}
]
}},
"confidence": 0.9
}}
Note: Extract structured data from detailed input. Use kontextInformationen for metadata. Each item has 'thema' (topic) and 'inhalt' (content as text).
- Input: "Zeige mir alle Projekte"
Output: {{"intent": "READ", "entity": "Projekt", "parameters": {{}}, "confidence": 0.9}}
- Input: "Zeige mir Projekte in Zürich"
Output: {{"intent": "READ", "entity": "Parzelle", "parameters": {{"kontextGemeinde": "Zürich"}}, "confidence": 0.9}}
Note: Location queries should query Parzelle, not Projekt directly
- Input: "Zeige mir Projekte in Zürich" or "Wie viele Projekte in Zürich"
Output: {{"intent": "READ", "entity": "Projekt", "parameters": {{"location_filter": "Zürich"}}, "confidence": 0.9}}
Note: For project location queries, use Projekt entity with location_filter parameter
- Input: "Zeige mir Parzellen mit PLZ 8000"
Output: {{"intent": "READ", "entity": "Parzelle", "parameters": {{"plz": "8000"}}, "confidence": 0.95}}
@ -233,6 +462,16 @@ Examples:
- Input: "Lösche Parzelle ABC"
Output: {{"intent": "DELETE", "entity": "Parzelle", "parameters": {{"id": "ABC"}}, "confidence": 0.9}}
IMPORTANT EXTRACTION RULES:
1. For CREATE operations, extract ALL mentioned data fields from the user input
2. Use kontextInformationen array for metadata that doesn't have dedicated fields (EGRID, BFS numbers, area, coordinates, etc.)
3. Each kontextInformationen item MUST have exactly two fields: 'thema' (topic/subject) and 'inhalt' (content as text string)
4. Format kontextInformationen values as readable text strings, including units (e.g., "6514.99 m²", "X: 123, Y: 456")
5. Match field names EXACTLY to the entity definition above
6. Convert data types correctly (strings for text, numbers for numeric values)
7. Extract coordinates, areas, and other numeric values from text
8. When multiple values are mentioned for the same concept (ID, Nummer, Name), use the most relevant one for 'label' and put alternatives in parzellenAliasTags
"""
try:
@ -335,15 +574,56 @@ async def executeIntentBasedOperation(
elif entity == "Parzelle":
# Create Parzelle from parameters
parzelle = Parzelle(
mandateId=currentUser.mandateId,
label=parameters.get("label", ""),
strasseNr=parameters.get("strasseNr"),
plz=parameters.get("plz"),
bauzone=parameters.get("bauzone"),
kontextGemeinde=parameters.get("kontextGemeinde"),
)
# Import Kontext for kontextInformationen
from modules.datamodels.datamodelRealEstate import Kontext, GeoPolylinie
# Build parzelle data with all extracted parameters
parzelle_data = {
"mandateId": currentUser.mandateId,
"label": parameters.get("label", ""),
}
# Add optional fields if present
optional_fields = [
"parzellenAliasTags", "eigentuemerschaft", "strasseNr", "plz",
"bauzone", "az", "bz", "vollgeschossZahl", "anrechenbarDachgeschoss",
"anrechenbarUntergeschoss", "gebaeudehoeheMax", "kontextGemeinde",
"regelnGrenzabstand", "regelnMehrlaengenzuschlag", "regelnMehrhoehenzuschlag",
"parzelleBebaut", "parzelleErschlossen", "parzelleHanglage",
"laermschutzzone", "hochwasserschutzzone", "grundwasserschutzzone"
]
for field in optional_fields:
if field in parameters and parameters[field] is not None:
parzelle_data[field] = parameters[field]
# Handle complex objects
if "perimeter" in parameters and parameters["perimeter"]:
parzelle_data["perimeter"] = GeoPolylinie(**parameters["perimeter"])
if "baulinie" in parameters and parameters["baulinie"]:
parzelle_data["baulinie"] = GeoPolylinie(**parameters["baulinie"])
# Handle kontextInformationen (convert dicts to Kontext objects)
if "kontextInformationen" in parameters and parameters["kontextInformationen"]:
kontext_list = []
for kontext_data in parameters["kontextInformationen"]:
if isinstance(kontext_data, dict):
# Ensure only thema and inhalt are passed (Kontext model only has these fields)
kontext_obj = Kontext(
thema=kontext_data.get("thema", ""),
inhalt=kontext_data.get("inhalt", "")
)
kontext_list.append(kontext_obj)
else:
kontext_list.append(kontext_data)
parzelle_data["kontextInformationen"] = kontext_list
parzelle = Parzelle(**parzelle_data)
created = realEstateInterface.createParzelle(parzelle)
logger.info(f"Created Parzelle '{created.label}' with {len(created.kontextInformationen)} context items")
return {
"operation": "CREATE",
"entity": "Parzelle",
@ -438,17 +718,67 @@ async def executeIntentBasedOperation(
k: v for k, v in parameters.items()
if k != "id" and k in validProjektFields
}
# Warn about invalid fields
invalidFields = {k: v for k, v in parameters.items() if k not in validProjektFields and k != "id"}
if invalidFields:
logger.warning(f"Invalid filter fields for Projekt ignored: {list(invalidFields.keys())}")
logger.info("Note: Location queries should use Parzelle entity, not Projekt")
# Handle location_filter specially (filter projects by parcel location)
location_filter = parameters.get("location_filter")
# Get all projects first
projekte = realEstateInterface.getProjekte(recordFilter=recordFilter if recordFilter else None)
# If location filter is present, filter by parcels in that location
if location_filter:
logger.info(f"Filtering projects by location: {location_filter}")
# Try to resolve location to Gemeinde ID for UUID comparison
location_id = None
try:
# Check if it's already a UUID
import re
uuid_pattern = re.compile(r'^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$', re.IGNORECASE)
if not uuid_pattern.match(location_filter):
# Try to resolve name to ID
gemeinde_records = realEstateInterface.getGemeinden(recordFilter={"label": location_filter})
if gemeinde_records:
location_id = gemeinde_records[0].id
logger.debug(f"Resolved location '{location_filter}' to ID '{location_id}'")
except Exception as e:
logger.debug(f"Could not resolve location filter: {e}")
filtered_projekte = []
for projekt in projekte:
# Check if any parcel in the project matches the location
for parzelle in projekt.parzellen:
# Check kontextGemeinde (both UUID and string), plz, or strasseNr for location match
location_lower = location_filter.lower()
matches = False
# Check if kontextGemeinde matches (as UUID or string)
if parzelle.kontextGemeinde:
if (parzelle.kontextGemeinde == location_id or # UUID match
parzelle.kontextGemeinde == location_filter or # Exact match
location_lower in parzelle.kontextGemeinde.lower()): # Partial string match
matches = True
# Check PLZ or address
if not matches and (
(parzelle.plz and location_lower in parzelle.plz) or
(parzelle.strasseNr and location_lower in parzelle.strasseNr.lower())
):
matches = True
if matches:
filtered_projekte.append(projekt)
break # Found a matching parcel, no need to check more
projekte = filtered_projekte
logger.info(f"Found {len(projekte)} projects in location '{location_filter}'")
return {
"operation": "READ",
"entity": "Projekt",
"result": [p.model_dump() for p in projekte]
"result": [p.model_dump() for p in projekte],
"count": len(projekte)
}
elif entity == "Parzelle":
parzelleId = parameters.get("id")
@ -484,10 +814,26 @@ async def executeIntentBasedOperation(
logger.warning(f"Invalid filter fields for Parzelle ignored: {list(invalidFields.keys())}")
parzellen = realEstateInterface.getParzellen(recordFilter=recordFilter if recordFilter else None)
# Debug logging for empty results
if not parzellen and recordFilter:
logger.info(f"No Parzellen found matching filter: {recordFilter}")
# Get total count to help debug
all_parzellen = realEstateInterface.getParzellen(recordFilter=None)
logger.info(f"Total Parzellen in database: {len(all_parzellen)}")
if all_parzellen:
# Show some sample kontextGemeinde values
sample_gemeinden = set()
for p in all_parzellen[:10]:
if p.kontextGemeinde:
sample_gemeinden.add(p.kontextGemeinde)
logger.info(f"Sample kontextGemeinde values in database: {sample_gemeinden}")
return {
"operation": "READ",
"entity": "Parzelle",
"result": [p.model_dump() for p in parzellen]
"result": [p.model_dump() for p in parzellen],
"count": len(parzellen)
}
elif entity == "Gemeinde":
from modules.datamodels.datamodelRealEstate import Gemeinde
@ -507,7 +853,8 @@ async def executeIntentBasedOperation(
return {
"operation": "READ",
"entity": "Gemeinde",
"result": [g.model_dump() for g in gemeinden]
"result": [g.model_dump() for g in gemeinden],
"count": len(gemeinden)
}
elif entity == "Kanton":
from modules.datamodels.datamodelRealEstate import Kanton
@ -527,7 +874,8 @@ async def executeIntentBasedOperation(
return {
"operation": "READ",
"entity": "Kanton",
"result": [k.model_dump() for k in kantone]
"result": [k.model_dump() for k in kantone],
"count": len(kantone)
}
elif entity == "Land":
from modules.datamodels.datamodelRealEstate import Land
@ -547,7 +895,8 @@ async def executeIntentBasedOperation(
return {
"operation": "READ",
"entity": "Land",
"result": [l.model_dump() for l in laender]
"result": [l.model_dump() for l in laender],
"count": len(laender)
}
elif entity == "Dokument":
from modules.datamodels.datamodelRealEstate import Dokument
@ -567,7 +916,8 @@ async def executeIntentBasedOperation(
return {
"operation": "READ",
"entity": "Dokument",
"result": [d.model_dump() for d in dokumente]
"result": [d.model_dump() for d in dokumente],
"count": len(dokumente)
}
else:
raise ValueError(f"READ operation not supported for entity: {entity}")

View file

@ -220,12 +220,30 @@ class RealEstateObjects:
def getParzellen(self, recordFilter: Optional[Dict[str, Any]] = None) -> List[Parzelle]:
"""Get all plots matching the filter."""
original_gemeinde_value = None
# Resolve location names to IDs if needed
if recordFilter:
# Save original value before resolution for fallback search
if "kontextGemeinde" in recordFilter:
original_gemeinde_value = recordFilter["kontextGemeinde"]
recordFilter = self._resolveLocationFilters(recordFilter)
records = self.db.getRecordset(Parzelle, recordFilter=recordFilter or {})
# Fallback: If no records found and we resolved a Gemeinde name,
# try searching with the original name for backwards compatibility
# (handles case where data has string names instead of UUIDs)
if not records and original_gemeinde_value and recordFilter and "kontextGemeinde" in recordFilter:
if recordFilter["kontextGemeinde"] != original_gemeinde_value:
logger.info(f"No results with resolved UUID, trying with original name '{original_gemeinde_value}'")
fallback_filter = recordFilter.copy()
fallback_filter["kontextGemeinde"] = original_gemeinde_value
records = self.db.getRecordset(Parzelle, recordFilter=fallback_filter)
if records:
logger.info(f"Found {len(records)} records using original name (legacy data format)")
# Apply access control
filtered = self.access.uam(Parzelle, records)