From e5ba272b1bf27966e4a557ccd3532c8f98c30c02 Mon Sep 17 00:00:00 2001 From: G0DSEND016 Date: Mon, 15 Dec 2025 23:21:10 +0100 Subject: [PATCH] Code improvements and API interactions --- app/app.py | 6 +- core/.env | 1 - core/{tools => api}/__init__.py | 0 core/api/fetch_api_data.py | 23 ++++ core/api/schemas.py | 178 ++++++++++++++++++++++++++++ core/api/tools/__init__.py | 0 core/api/tools/admin_proceedings.py | 54 +++++++++ core/api/tools/civil_proceedings.py | 56 +++++++++ core/api/tools/contracts.py | 53 +++++++++ core/api/tools/coutrs.py | 52 ++++++++ core/api/tools/decisions.py | 53 +++++++++ core/api/tools/judges.py | 54 +++++++++ core/initialize_agent.py | 58 +++++++++ core/model.py | 116 ------------------ core/stream_response.py | 13 ++ core/system_prompt.py | 59 +++++++++ core/tools/obcianPojednavania.py | 137 --------------------- core/tools/rozhodnutie.py | 141 ---------------------- core/tools/spravneKonanie.py | 142 ---------------------- core/tools/sud.py | 114 ------------------ core/tools/sudca.py | 126 -------------------- core/tools/zmluvy.py | 121 ------------------- requirements.txt | 4 +- 23 files changed, 659 insertions(+), 902 deletions(-) delete mode 100644 core/.env rename core/{tools => api}/__init__.py (100%) create mode 100644 core/api/fetch_api_data.py create mode 100644 core/api/schemas.py create mode 100644 core/api/tools/__init__.py create mode 100644 core/api/tools/admin_proceedings.py create mode 100644 core/api/tools/civil_proceedings.py create mode 100644 core/api/tools/contracts.py create mode 100644 core/api/tools/coutrs.py create mode 100644 core/api/tools/decisions.py create mode 100644 core/api/tools/judges.py create mode 100644 core/initialize_agent.py delete mode 100644 core/model.py create mode 100644 core/stream_response.py create mode 100644 core/system_prompt.py delete mode 100644 core/tools/obcianPojednavania.py delete mode 100644 core/tools/rozhodnutie.py delete mode 100644 core/tools/spravneKonanie.py delete mode 100644 core/tools/sud.py delete mode 100644 core/tools/sudca.py delete mode 100644 core/tools/zmluvy.py diff --git a/app/app.py b/app/app.py index 446febd..0dc8dfc 100644 --- a/app/app.py +++ b/app/app.py @@ -1,7 +1,7 @@ -import asyncio from datetime import datetime import streamlit as st -from core.model import assistant_agent, SQLiteSession +from core.initialize_agent import assistant_agent +from core.stream_response import SQLiteSession from app.components.sidebar import add_sidebar style_chat_message = """ @@ -78,7 +78,7 @@ def create_app() -> None: try: response = st.write_stream(assistant_agent(request, st.session_state.chat_session)) except Exception as e: - response = f"⚠️ Error: {e}" + response = f"️⚠️🌐 Error: {e}" finally: assistant_time = get_time() diff --git a/core/.env b/core/.env deleted file mode 100644 index da67259..0000000 --- a/core/.env +++ /dev/null @@ -1 +0,0 @@ -OPENAI_API_KEY="" \ No newline at end of file diff --git a/core/tools/__init__.py b/core/api/__init__.py similarity index 100% rename from core/tools/__init__.py rename to core/api/__init__.py diff --git a/core/api/fetch_api_data.py b/core/api/fetch_api_data.py new file mode 100644 index 0000000..0424a4d --- /dev/null +++ b/core/api/fetch_api_data.py @@ -0,0 +1,23 @@ +import httpx + +async def fetch_api_data(icon: str, url: str, params: dict, remove_keys: list = None) -> dict: + try: + print(f"🔨{icon}Input parameters: {params}") + async with httpx.AsyncClient() as client: + response = await client.get(url, params=params, timeout=10.0) + response.raise_for_status() + print(f"🖇️{icon}Request URL: {response.url}") + + data = response.json() + if remove_keys and isinstance(data, dict): + for key in remove_keys: + data.pop(key, None) + print(f"🚮{icon}Successfully removed key: {key}") + return data + + except httpx.HTTPStatusError as e: + return {"error": "http_error", "status_code": e.response.status_code, "detail": e.response.text} + except httpx.RequestError as e: + return {"error": "request_error", "status_code": str(e)} + except Exception as e: + return {"error": "unexpected_error", "status_code": str(e)} diff --git a/core/api/schemas.py b/core/api/schemas.py new file mode 100644 index 0000000..2f48dc9 --- /dev/null +++ b/core/api/schemas.py @@ -0,0 +1,178 @@ +from pydantic import BaseModel, Field, conint +from typing import Optional, List, Literal + +# ================================================================================================================= +# COURT SCHEMAS +# ================================================================================================================= + +class Court(BaseModel): + query: Optional[str] = Field(None, description="Search term or phrase") + typSuduFacetFilter: Optional[List[str]] = Field(None, description="Court type (facet filter)") + krajFacetFilter: Optional[List[str]] = Field(None, description="Region (facet filter)") + okresFacetFilter: Optional[List[str]] = Field(None, description="District (facet filter)") + zahrnutZaniknuteSudy: Optional[bool] = Field(None, description="Flag to filter defunct/inactive courts") + page: Optional[conint(ge=1)] = Field(None, description="Requested page number (starting from 1)") + size: Optional[conint(ge=1)] = Field(None, description="Number of results per page") + indexDatumOd: Optional[str] = Field(None, description="Index date from (format YYYY-MM-DD)") + indexDatumDo: Optional[str] = Field(None, description="Index date to (format YYYY-MM-DD)") + sortProperty: Optional[str] = Field(None, description="Field to sort the output by") + sortDirection: Literal["ASC", "DESC"] = Field("ASC", description="Sort direction (ASC or DESC)") + +class CourtID(BaseModel): + id: str = Field(..., description="Court identifier (e. g., sud_175)") + +class CourtAutocomplete(BaseModel): + query: Optional[str] = Field(None, description="Search term or phrase") + limit: Optional[conint(ge=1)] = Field(None, description="Limits the number of returned results (pagination)") + + +# ================================================================================================================= +# JUDGE SCHEMAS +# ================================================================================================================= + +class Judge(BaseModel): + query: Optional[str] = Field(None, description="Search term or phrase") + funkciaFacetFilter: Optional[List[str]] = Field(None, description="Judge function (facet filter)") + typSuduFacetFilter: Optional[List[str]] = Field(None, description="Court type (facet filter)") + krajFacetFilter: Optional[List[str]] = Field(None, description="Region (facet filter)") + okresFacetFilter: Optional[List[str]] = Field(None, description="District (facet filter)") + stavZapisuFacetFilter: Optional[List[str]] = Field(None, description="Record status (facet filter)") + guidSud: Optional[str] = Field(None, description="Court identifier (e.g., sud_100)") + indexDatumOd: Optional[str] = Field(None, description="Index date from (format YYYY-MM-DD)") + indexDatumDo: Optional[str] = Field(None, description="Index date to (format YYYY-MM-DD)") + page: Optional[conint(ge=1)] = Field(None, description="Requested page number (starting from 1)") + size: Optional[conint(ge=1)] = Field(None, description="Number of results per page") + sortProperty: Optional[str] = Field(None, description="Field to sort the output by") + sortDirection: Literal["ASC", "DESC"] = Field("ASC", description="Sort direction (ASC or DESC)") + +class JudgeID(BaseModel): + id: str = Field(..., description="Judge identifier (e. g., sudca_1)") + +class JudgeAutocomplete(BaseModel): + query: Optional[str] = Field(None, description="Search term or phrase") + guidSud: Optional[str] = Field(None, description="Court identifier (e.g., sud_100)") + limit: Optional[conint(ge=1)] = Field(None, description="Limits the number of returned results (pagination)") + + +# ================================================================================================================= +# CONTRACTS SCHEMAS +# ================================================================================================================= + +class Contracts(BaseModel): + query: Optional[str] = Field(None, description="Search term or phrase") + typDokumentuFacetFilter: Optional[List[str]] = Field(None, description="Contract's type (facet filter)") + odberatelFacetFilter: Optional[List[str]] = Field(None, description="Subscriber filter") + dodavatelFacetFilter: Optional[List[str]] = Field(None, description="Supplier filter") + hodnotaZmluvyFacetFilter: Optional[List[str]] = Field(None, description="Contract value in EUR filter") + datumZverejeneniaOd: Optional[str] = Field(None, description="Index date from (format YYYY-MM-DD)") + datumZverejeneniaDo: Optional[str] = Field(None, description="Index date to (format YYYY-MM-DD)") + guidSud: Optional[str] = Field(None, description="Court identifier (e.g., sud_100)") + indexDatumOd: Optional[str] = Field(None, description="Index date from (format YYYY-MM-DD)") + indexDatumDo: Optional[str] = Field(None, description="Index date to (format YYYY-MM-DD)") + sortProperty: Optional[str] = Field(None, description="Field to sort the output by") + sortDirection: Literal["ASC", "DESC"] = Field("ASC", description="Sort direction (ASC or DESC)") + page: Optional[conint(ge=1)] = Field(None, description="Requested page number (starting from 1)") + size: Optional[conint(ge=1)] = Field(None, description="Number of results per page") + +class ContractID(BaseModel): + idZmluvy: str = Field(..., description="Contract identifier (e. g., 2156252)") + +class ContractAutocomplete(BaseModel): + query: Optional[str] = Field(None, description="Search term or phrase") + guidSud: Optional[str] = Field(None, description="Court identifier (e.g., sud_100)") + limit: Optional[conint(ge=1)] = Field(None, description="Limits the number of returned results (pagination)") + + +# ================================================================================================================= +# DECISION SCHEMAS +# ================================================================================================================= + +class Decision(BaseModel): + query: Optional[str] = Field(None, description="Search term or phrase") + typSuduFacetFilter: Optional[List[str]] = Field(None, description="Court type (facet filter)") + krajFacetFilter: Optional[List[str]] = Field(None, description="Region (facet filter)") + okresFacetFilter: Optional[List[str]] = Field(None, description="District (facet filter)") + odkazovanePredpisy: Optional[str] = Field(None, description="Referenced regulations") + oblastPravnejUpravyFacetFilter: Optional[List[str]] = Field(None, description="Area of legal regulation (facet filter)") + podOblastPravnejUpravyFacetFilter: Optional[List[str]] = Field(None, description="Sub-area of legal regulation (facet filter)") + formaRozhodnutiaFacetFilter: Optional[List[str]] = Field(None, description="Form of decision (facet filter)") + povahaRozhodnutiaFacetFilter: Optional[str] = Field(None, description="Nature of decision") + vydaniaOd: Optional[str] = Field(None, description="Issue date from") + vydaniaDo: Optional[str] = Field(None, description="Issue date to") + ecli: Optional[str] = Field(None, description="ECLI identifier") + spisovaZnacka: Optional[str] = Field(None, description="Case reference number") + cisloSpisu: Optional[str] = Field(None, description="File identification number") + guidSudca: Optional[str] = Field(None, description="Judge identifier (e.g., sudca_1)") + guidSud: Optional[str] = Field(None, description="Court identifier (e.g., sud_100)") + indexDatumOd: Optional[str] = Field(None, description="Index date from (format YYYY-MM-DD)") + indexDatumDo: Optional[str] = Field(None, description="Index date to (format YYYY-MM-DD)") + sortProperty: Optional[str] = Field(None, description="Field to sort the output by") + sortDirection: Literal["ASC", "DESC"] = Field("ASC", description="Sort direction (ASC or DESC)") + page: Optional[conint(ge=1)] = Field(None, description="Requested page number (starting from 1)") + size: Optional[conint(ge=1)] = Field(None, description="Number of results per page") + +class DecisionID(BaseModel): + id: str = Field(..., description="Decision identifier (e.g., a3310194-e9ac-4e6b-bfbd-25c40f26938b:1097de02-3389-405b-98a4-df7abea3f9ec)") + +class DecisionAutocomplete(BaseModel): + query: Optional[str] = Field(None, description="Search term or phrase") + guidSud: Optional[str] = Field(None, description="Court identifier (e.g., sud_100)") + limit: Optional[conint(ge=1)] = Field(None, description="Limits the number of returned results (pagination)") + + +# ================================================================================================================= +# CIVIL PROCEEDINGS SCHEMAS +# ================================================================================================================= + +class CivilProceedings(BaseModel): + query: Optional[str] = Field(None, description="Search term or phrase") + typSuduFacetFilter: Optional[List[str]] = Field(None, description="Court type (facet filter)") + krajFacetFilter: Optional[List[str]] = Field(None, description="Region (facet filter)") + okresFacetFilter: Optional[List[str]] = Field(None, description="District (facet filter)") + usekFacetFilter: Optional[List[str]] = Field(None, description="List of sections (facet filter)") + formaUkonuFacetFilter: Optional[List[str]] = Field(None, description="List of action types (facet filter)") + pojednavaniaOd: Optional[str] = Field(None, description="Hearing date from (DD.MM.YYYY)") + pojednavaniaDo: Optional[str] = Field(None, description="Hearing date to (DD.MM.YYYY)") + guidSudca: Optional[str] = Field(None, description="Judge identifier (e.g., sudca_1)") + guidSud: Optional[str] = Field(None, description="Court identifier (e.g., sud_100)") + spisovaZnacka: Optional[str] = Field(None,description="Case reference number") + verejneVyhlasenie: Optional[bool] = Field(None,description="Flag indicating whether the announcement is public") + indexDatumOd: Optional[str] = Field(None, description="Index date from (format YYYY-MM-DD)") + indexDatumDo: Optional[str] = Field(None, description="Index date to (format YYYY-MM-DD)") + sortProperty: Optional[str] = Field(None, description="Field to sort the output by") + sortDirection: Literal["ASC", "DESC"] = Field("ASC", description="Sort direction (ASC or DESC)") + page: Optional[conint(ge=1)] = Field(None, description="Requested page number (starting from 1)") + size: Optional[conint(ge=1)] = Field(None, description="Number of results per page") + +class CivilProceedingsID(BaseModel): + id: str = Field(..., description="Identifier (e.g., 121e4d31-695e-41e1-9191-7c9ad5d8d484)") + +class CivilProceedingsAutocomplete(BaseModel): + query: Optional[str] = Field(None, description="Search term or phrase") + guidSud: Optional[str] = Field(None, description="Court identifier (e.g., sud_100)") + guidSudca: Optional[str] = Field(None, description="Judge identifier (e.g., sudca_1)") + verejneVyhlasenie: Optional[bool] = Field(None,description="Flag indicating whether the announcement is public") + limit: Optional[conint(ge=1)] = Field(None, description="Limits the number of returned results (pagination)") + + +# ================================================================================================================= +# ADMINISTRATIVE PROCEEDINGS SCHEMAS +# ================================================================================================================= + +class AdministrativeProceedings(BaseModel): + query: Optional[str] = Field(None, description="Search term or phrase") + druhFacetFilter: Optional[List[str]] = Field(None, description="List of types (faceted filter)") + datumPravoplatnostiOd: Optional[str] = Field(None, description="Validity date from (DD.MM.YYYY)") + datumPravoplatnostiDo: Optional[str] = Field(None, description="Validity date to (DD.MM.YYYY)") + page: Optional[conint(ge=1)] = Field(None, description="Requested page number (starting from 1)") + size: Optional[conint(ge=1)] = Field(None, description="Number of results per page") + sortProperty: Optional[str] = Field(None, description="Field to sort the output by") + sortDirection: Literal["ASC", "DESC"] = Field("ASC", description="Sort direction (ASC or DESC)") + +class AdministrativeProceedingsID(BaseModel): + id: str = Field(..., description="Identifier of administrative proceedings (e.g., spravneKonanie_103)") + +class AdministrativeProceedingsAutocomplete(BaseModel): + query: Optional[str] = Field(None, description="Search term or phrase") + limit: Optional[conint(ge=1)] = Field(None, description="Limits the number of returned results (pagination)") + diff --git a/core/api/tools/__init__.py b/core/api/tools/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/core/api/tools/admin_proceedings.py b/core/api/tools/admin_proceedings.py new file mode 100644 index 0000000..a0eb7f2 --- /dev/null +++ b/core/api/tools/admin_proceedings.py @@ -0,0 +1,54 @@ +from core.api.fetch_api_data import fetch_api_data +from core.api.schemas import (AdministrativeProceedings, + AdministrativeProceedingsID, + AdministrativeProceedingsAutocomplete) +from agents import function_tool + +BASE_URL = "https://obcan.justice.sk/pilot/api/ress-isu-service" + +class AdminProceedingsAPI: + + @function_tool + async def admin_proceedings(self, params: AdministrativeProceedings) -> dict: + """ + Fetch a list of administrative proceedings from the Justice API with optional filtering. + + Args: + params (AdministrativeProceedings): Filtering and pagination parameters. + + Returns: + dict: A dictionary containing a list of administrative proceedings and related metadata. + """ + url = f"{BASE_URL}/v1/spravneKonanie" + + return await fetch_api_data(icon="✒️", url=url, params=params.model_dump(exclude_none=True)) + + @function_tool + async def admin_proceedings_id(self, params: AdministrativeProceedingsID) -> dict: + """ + Fetch detailed information about a specific administrative proceeding by its identifier. + + Args: + params (AdministrativeProceedingsID): Unique identifier of the administrative proceeding. + + Returns: + dict: Details of the specified administrative proceeding. + """ + url = f"{BASE_URL}/v1/spravneKonanie/{params.id}" + + return await fetch_api_data(icon="✒️", url=url, params=params.model_dump(exclude_none=True)) + + @function_tool + async def admin_proceedings_autocomplete(self, params: AdministrativeProceedingsAutocomplete) -> dict: + """ + Fetch autocomplete suggestions for administrative proceeding search terms. + + Args: + params (AdministrativeProceedingsAutocomplete): Parameters for autocomplete query (e.g., partial text). + + Returns: + dict: Suggested values matching the input query. + """ + url = f"{BASE_URL}/v1/spravneKonanie/autocomplete" + + return await fetch_api_data(icon="✒️", url=url, params=params.model_dump(exclude_none=True)) \ No newline at end of file diff --git a/core/api/tools/civil_proceedings.py b/core/api/tools/civil_proceedings.py new file mode 100644 index 0000000..4c6d3b1 --- /dev/null +++ b/core/api/tools/civil_proceedings.py @@ -0,0 +1,56 @@ +from core.api.fetch_api_data import fetch_api_data +from core.api.schemas import (CivilProceedings, + CivilProceedingsID, + CivilProceedingsAutocomplete) +from agents import function_tool + +BASE_URL = "https://obcan.justice.sk/pilot/api/ress-isu-service" + +class CivilProceedingsAPI: + + @function_tool + async def civil_proceedings(self, params: CivilProceedings) -> dict: + """ + Fetch a list of civil proceedings and publicly announced judgments + from the Justice API with optional filtering. + + Args: + params (CivilProceedings): Filtering and pagination parameters. + + Returns: + dict: A dictionary containing a list of civil proceedings and related metadata. + """ + url = f"{BASE_URL}/v1/obcianPojednavania" + + return await fetch_api_data(icon="🖊️", url=url, params=params.model_dump(exclude_none=True)) + + @function_tool + async def civil_proceedings_id(self, params: CivilProceedingsID) -> dict: + """ + Fetch detailed information about a specific civil proceeding + and publicly announced judgment by its identifier. + + Args: + params (CivilProceedingsID): Unique identifier of the civil proceeding. + + Returns: + dict: Details of the specified civil proceeding and judgment. + """ + url = f"{BASE_URL}/v1/obcianPojednavania/{params.id}" + + return await fetch_api_data(icon="🖊️", url=url, params=params.model_dump(exclude_none=True)) + + @function_tool + async def civil_proceedings_autocomplete(self, params: CivilProceedingsAutocomplete) -> dict: + """ + Fetch autocomplete suggestions for civil proceeding search terms. + + Args: + params (CivilProceedingsAutocomplete): Parameters for autocomplete query (e.g., partial text). + + Returns: + dict: Suggested values matching the input query. + """ + url = f"{BASE_URL}/v1/obcianPojednavania/autocomplete" + + return await fetch_api_data(icon="🖊️", url=url, params=params.model_dump(exclude_none=True)) \ No newline at end of file diff --git a/core/api/tools/contracts.py b/core/api/tools/contracts.py new file mode 100644 index 0000000..241b580 --- /dev/null +++ b/core/api/tools/contracts.py @@ -0,0 +1,53 @@ +from core.api.fetch_api_data import fetch_api_data +from core.api.schemas import Contracts, ContractID, ContractAutocomplete +from agents import function_tool + +BASE_URL = 'https://obcan.justice.sk/pilot/api/ress-isu-service' + +class ContractsAPI: + + @function_tool + async def contract(self, params: Contracts) -> dict: + """ + Fetch a list of contracts from the Justice API with optional filtering. + + Args: + params (Contracts): Filtering and pagination parameters. + + Returns: + dict: A dictionary containing a list of contracts and related metadata. + """ + url = f"{BASE_URL}/v1/zmluvy" + + return await fetch_api_data(icon="📃", url=url, params=params.model_dump(exclude_none=True)) + + + @function_tool + async def contract_id(self, params: ContractID) -> dict: + """ + Fetch detailed information about a specific contract by its identifier. + + Args: + params (ContractID): Unique identifier of the contract. + + Returns: + dict: Details of the specified contract. + """ + url = f"{BASE_URL}/v1/zmluvy/{params.id}" + + return await fetch_api_data(icon="📃", url=url, params=params.model_dump(exclude_none=True)) + + @function_tool + async def contract_autocomplete(self, params: ContractAutocomplete) -> dict: + """ + Fetch autocomplete suggestions for contract-related search terms. + + Args: + params (ContractAutocomplete): Parameters for autocomplete query (e.g., partial text). + + Returns: + dict: Suggested values matching the input query. + """ + url = f"{BASE_URL}/v1/zmluvy/autocomplete" + + return await fetch_api_data(icon="📃", url=url, params=params.model_dump(exclude_none=True)) \ No newline at end of file diff --git a/core/api/tools/coutrs.py b/core/api/tools/coutrs.py new file mode 100644 index 0000000..5e2b2e9 --- /dev/null +++ b/core/api/tools/coutrs.py @@ -0,0 +1,52 @@ +from core.api.fetch_api_data import fetch_api_data +from core.api.schemas import Court, CourtID, CourtAutocomplete +from agents import function_tool + +BASE_URL = 'https://obcan.justice.sk/pilot/api/ress-isu-service' + +class CourtsAPI: + + @function_tool + async def court(self, params: Court) -> dict: + """ + Fetch a list of courts from the Justice API with optional filtering. + + Args: + params (Court): Filtering and pagination parameters. + + Returns: + dict: A dictionary containing a list of courts and related metadata. + """ + url = f"{BASE_URL}/v1/sud" + + return await fetch_api_data(icon="🏛️️", url=url, params=params.model_dump(exclude_none=True)) + + @function_tool + async def court_id(self, params: CourtID) -> dict: + """ + Fetch detailed information about a specific court by its identifier. + + Args: + params (CourtID): Unique identifier of the court. + + Returns: + dict: Details of the specified court. + """ + url = f"{BASE_URL}/v1/sud/{params.id}" + + return await fetch_api_data(icon="🏛️️", url=url, params=params.model_dump(exclude_none=True), remove_keys=['foto']) + + @function_tool + async def court_autocomplete(self, params: CourtAutocomplete) -> dict: + """ + Fetch autocomplete suggestions for court names. + + Args: + params (CourtAutocomplete): Parameters for autocomplete. + + Returns: + dict: Suggested court names matching the input query. + """ + url = f"{BASE_URL}/v1/sud/autocomplete" + + return await fetch_api_data(icon="🏛️️", url=url, params=params.model_dump(exclude_none=True)) diff --git a/core/api/tools/decisions.py b/core/api/tools/decisions.py new file mode 100644 index 0000000..8e063f1 --- /dev/null +++ b/core/api/tools/decisions.py @@ -0,0 +1,53 @@ +from core.api.fetch_api_data import fetch_api_data +from core.api.schemas import Decision, DecisionID, DecisionAutocomplete +from agents import function_tool + +BASE_URL = 'https://obcan.justice.sk/pilot/api/ress-isu-service' + +class DecisionsAPI: + + @function_tool + async def decision(self, params: Decision) -> dict: + """ + Fetch a list of decisions from the Justice API with optional filtering. + + Args: + params (Decision): Filtering and pagination parameters. + + Returns: + dict: A dictionary containing a list of decisions and related metadata. + """ + url = f"{BASE_URL}/v1/rozhodnutie" + + return await fetch_api_data(icon="⚖️️", url=url, params=params.model_dump(exclude_none=True)) + + + @function_tool + async def decision_id(self, params: DecisionID) -> dict: + """ + Fetch detailed information about a specific decision by its identifier. + + Args: + params (DecisionID): Unique identifier of the decision. + + Returns: + dict: Details of the specified decision. + """ + url = f"{BASE_URL}/v1/rozhodnutie/{params.id}" + + return await fetch_api_data(icon="⚖️️", url=url, params=params.model_dump(exclude_none=True)) + + @function_tool + async def decision_autocomplete(self, params: DecisionAutocomplete) -> dict: + """ + Fetch autocomplete suggestions for decision-related search terms. + + Args: + params (DecisionAutocomplete): Parameters for autocomplete. + + Returns: + dict: Suggested values matching the input query. + """ + url = f"{BASE_URL}/v1/rozhodnutie/autocomplete" + + return await fetch_api_data(icon="⚖️️", url=url, params=params.model_dump(exclude_none=True)) \ No newline at end of file diff --git a/core/api/tools/judges.py b/core/api/tools/judges.py new file mode 100644 index 0000000..b775346 --- /dev/null +++ b/core/api/tools/judges.py @@ -0,0 +1,54 @@ +from core.api.fetch_api_data import fetch_api_data +from core.api.schemas import Judge, JudgeID, JudgeAutocomplete +from agents import function_tool + +BASE_URL = 'https://obcan.justice.sk/pilot/api/ress-isu-service' + +class JudgesAPI: + + @function_tool + async def judge(self, params: Judge) -> dict: + """ + Fetch a list of judges from the Justice API with optional filtering. + + Args: + params (Judge): Filtering and pagination parameters. + + Returns: + dict: A dictionary containing a list of judges and related metadata. + """ + url = f"{BASE_URL}/v1/sudca" + + return await fetch_api_data(icon="🧑‍⚖️", url=url, params=params.model_dump(exclude_none=True), remove_keys=['sudcaMapList']) + + + @function_tool + async def judge_id(self, params: JudgeID) -> dict: + """ + Fetch detailed information about a specific judge by their identifier. + + Args: + params (JudgeID): Unique identifier of the judge. + + Returns: + dict: Details of the specified judge. + """ + url = f"{BASE_URL}/v1/sudca/{params.id}" + + return await fetch_api_data(icon="🧑‍⚖️", url=url, params=params.model_dump(exclude_none=True)) + + + @function_tool + async def judge_autocomplete(self, params: JudgeAutocomplete) -> dict: + """ + Fetch autocomplete suggestions for judges' names. + + Args: + params (JudgeAutocomplete): Parameters for autocomplete query (e.g., partial name). + + Returns: + dict: Suggested judge names matching the input query. + """ + url = f"{BASE_URL}/v1/sudca/autocomplete" + + return await fetch_api_data(icon="🧑‍⚖️", url=url, params=params.model_dump(exclude_none=True)) \ No newline at end of file diff --git a/core/initialize_agent.py b/core/initialize_agent.py new file mode 100644 index 0000000..233143c --- /dev/null +++ b/core/initialize_agent.py @@ -0,0 +1,58 @@ +from agents import Agent +from agents import OpenAIChatCompletionsModel, AsyncOpenAI, ModelSettings +from agents import set_tracing_disabled, enable_verbose_stdout_logging + +from core.system_prompt import SYSTEM_PROMPT +from core.stream_response import stream_response + +from core.api.tools.judges import JudgesAPI +from core.api.tools.coutrs import CourtsAPI +from core.api.tools.contracts import ContractsAPI +from core.api.tools.decisions import DecisionsAPI +from core.api.tools.admin_proceedings import AdminProceedingsAPI +from core.api.tools.civil_proceedings import CivilProceedingsAPI + +set_tracing_disabled(True) +#enable_verbose_stdout_logging() + +class BaseAgent(Agent[None]): pass + +def assistant_agent(prompt: str, session): + + judge_api = JudgesAPI() + court_api = CourtsAPI() + contract_api = ContractsAPI() + decision_api = DecisionsAPI() + admin_proceedings_api = AdminProceedingsAPI() + civil_proceedings_api = CivilProceedingsAPI() + + model = OpenAIChatCompletionsModel( + model="gpt-oss:20b-cloud", + openai_client=AsyncOpenAI(base_url="http://localhost:11434/v1", + api_key="ollama" + ) + ) + + agent = BaseAgent( + name="Assistant", + instructions=SYSTEM_PROMPT, + model=model, + model_settings=ModelSettings( + temperature=0.1, + tool_choice="auto", + parallel_tool_calls=False, + max_tokens=512, + ), + tools=[ + judge_api.judge, judge_api.judge_id, judge_api.judge_autocomplete, + court_api.court, court_api.court_id, court_api.court_autocomplete, + contract_api.contract, contract_api.contract_id, contract_api.contract_autocomplete, + decision_api.decision, decision_api.decision_id, decision_api.decision_autocomplete, + admin_proceedings_api.admin_proceedings, admin_proceedings_api.admin_proceedings_id, admin_proceedings_api.admin_proceedings_autocomplete, + civil_proceedings_api.civil_proceedings, civil_proceedings_api.civil_proceedings_id, civil_proceedings_api.civil_proceedings_autocomplete, + ], + tool_use_behavior="run_llm_again", + reset_tool_choice=True, + ) + + return stream_response(agent, prompt, session) \ No newline at end of file diff --git a/core/model.py b/core/model.py deleted file mode 100644 index bae1d87..0000000 --- a/core/model.py +++ /dev/null @@ -1,116 +0,0 @@ -from openai.types.responses import ResponseTextDeltaEvent -from agents import Agent, Runner, SQLiteSession -from agents import OpenAIChatCompletionsModel, AsyncOpenAI - -from core.tools.zmluvy import ContractsAPI -from core.tools.sud import CourtAPI -from core.tools.sudca import JudgeAPI -from core.tools.rozhodnutie import DecisionAPI -from core.tools.obcianPojednavania import CivilProceedingAPI -from core.tools.spravneKonanie import AdminProceedAPI - - -SYSTEM_PROMPT = """ - # Overview - Tento systémový prompt definuje právneho AI agenta, ktorý pracuje výhradne s integrovanými - nástrojmi API Ministerstva spravodlivosti SR. Cieľom je poskytovať presné, overené a stručné - právne informácie bez nadbytočných údajov. - - # Context - - Agent pracuje len s oficiálnymi verejnými databázami SR. - - Nepoužíva internet ani vlastné domnienky. - - V odpovediach uvádza zdroj: API Ministerstva spravodlivosti SR. - - Pri nejasných dopytoch žiada o spresnenie. - - Rešpektuje GDPR a neposkytuje právne rady, iba fakty. - - # Instructions - 1. Všetky dotazy spracúvaj výhradne cez dostupné nástroje. - 2. Pri zoznamoch vždy najprv použi autocomplete nástroj. - 3. Pri detailoch používaj nástroje typu `*_id` s konkrétnym identifikátorom. - 4. Dátumy vracaj vo formáte DD.MM.RRRR. - 5. Pri filtroch používaj hodnoty oddelené čiarkou bez medzier. - 6. Pri veľkých datasetoch používaj parametre page a size. - 7. Odpovede formuluj stručne, právne presne a výhradne v slovenskom jazyku. - 8. Ak nástroj nevráti výsledok, používateľovi to jasne oznám. - - # Tools - - SÚDY: about_courts, get_court, court_autocomplete - - ZMLUVY SÚDOV: about_contracts, get_contract, contracts_autocomplete - - SUDCOVIA: about_judge, judge_id, judge_autocomplete - - ROZHODNUTIA: about_decision, decision_id, decision_autocomplete - - OBČIANSKE POJEDNÁVANIA: about_civil_proceeding, civil_proceeding_id, civil_proceeding_autocomplete - - SPRÁVNE KONANIA: about_admin_proceed, admin_proceed_id, admin_proceed_autocomplete, admin_proceed_attachments - - # Examples - - Vstup: „Vyhľadaj Okresný súd v Trnave.“ - - Postup: použije sa court_autocomplete → get_court. - - Výstup: stručné potvrdenie s detailmi a zdrojom. - - - Vstup: „Nájdi rozhodnutie so spisovou značkou XY.“ - - Postup: decision_autocomplete → decision_id. - - # SOP (Standard Operating Procedure) - 1. Identifikuj typ požiadavky (zoznam, detail, vyhľadávanie). - 2. Použi príslušný autocomplete na zistenie identifikátorov. - 3. Zavolaj detailný nástroj `*_id`. - 4. Spracuj odpoveď a zhrň ju do stručného a presného výstupu. - 5. Uveď zdroj dát. - 6. Ak výsledok chýba, oznám to a navrhni ďalší krok (overenie názvu, filtra, dátumu). - - # Final Notes - - Agent odpovedá vždy len fakticky na základe API. - - Neposkytuje interpretácie ani právne rady. - - Výstup musí byť vecný, prehľadný a stredne dlhý. - -""" - -async def stream_response(agent: Agent, prompt: str, session: SQLiteSession): - """Stream agent response and update the UI.""" - - try: - result = Runner.run_streamed(agent, input=prompt, session=session) - async for event in result.stream_events(): - if event.type == "raw_response_event" and isinstance(event.data, ResponseTextDeltaEvent): - yield event.data.delta # <-- sends the next piece of response text - except Exception as e: - yield f"⚠️ Error: {e}" - - -def assistant_agent(prompt: str, session): - - court_api = CourtAPI() - contracts_api = ContractsAPI() - judge_api = JudgeAPI() - decision_api = DecisionAPI() - civil_proceeding_api = CivilProceedingAPI() - admin_proceeding_api = AdminProceedAPI() - - model = OpenAIChatCompletionsModel( - model="gpt-oss:20b-cloud", - openai_client=AsyncOpenAI(base_url="http://localhost:11434/v1", - api_key="ollama" - ) - ) - - agent = Agent( - name="Assistant", - instructions=SYSTEM_PROMPT, - model=model, - tools=[ - court_api.about_courts, court_api.get_court, court_api.court_autocomplete, - - contracts_api.get_contract, contracts_api.about_contracts, contracts_api.contracts_autocomplete, - - judge_api.about_judge, judge_api.judge_id, judge_api.judge_autocomplete, - - decision_api.about_decision, decision_api.decision_id, decision_api.decision_autocomplete, - - civil_proceeding_api.about_civil_proceeding, civil_proceeding_api.civil_proceeding_id, - civil_proceeding_api.civil_proceeding_autocomplete, - - admin_proceeding_api.about_admin_proceed, admin_proceeding_api.admin_proceed_id, - admin_proceeding_api.admin_proceed_autocomplete, admin_proceeding_api.admin_proceed_attachments, - ] - ) - - return stream_response(agent, prompt, session) \ No newline at end of file diff --git a/core/stream_response.py b/core/stream_response.py new file mode 100644 index 0000000..00053da --- /dev/null +++ b/core/stream_response.py @@ -0,0 +1,13 @@ +from agents import Agent, Runner, SQLiteSession +from openai.types.responses import ResponseTextDeltaEvent + +async def stream_response(agent: Agent, prompt: str, session: SQLiteSession): + """Stream agent response and update the UI.""" + + try: + result = Runner.run_streamed(agent, input=prompt, session=session) + async for event in result.stream_events(): + if event.type == "raw_response_event" and isinstance(event.data, ResponseTextDeltaEvent): + yield event.data.delta # <-- sends the next piece of response text + except Exception as e: + yield f"⚠️🖨️ Error: {e}" diff --git a/core/system_prompt.py b/core/system_prompt.py new file mode 100644 index 0000000..7bcd1ad --- /dev/null +++ b/core/system_prompt.py @@ -0,0 +1,59 @@ +SYSTEM_PROMPT = """ + You are a Legal AI Assistant integrated with the Slovak Ministry of Justice API system. + + CORE PRINCIPLES: + 1. You are a specialized assistant that ONLY uses the provided tools to access legal information + 2. You MUST analyze the user's query and select the appropriate tool(s) based on the context + 3. You MUST extract relevant parameters from natural language queries and map them to the tool's expected parameters + 4. You MUST NOT invent or assume data - only use what the tools provide + 5. You MUST explain your reasoning and the limitations of the data when responding + + TOOL SELECTION GUIDELINES: + - judge: Use for queries about judges, their positions, locations, or counts. Can search by name, location, or other criteria. + - judge_id + - judge_autocomplete + + PARAMETER EXTRACTION PROCESS: + 1. Identify the main intent of the user's query + 2. Determine which tool(s) can fulfill this request + 3. Extract concrete values mentioned in the query: + - Person names (judges, court staff) + - Location names (convert to proper Slovak format if needed) + - Dates or date ranges + - Specific identifiers (court IDs) + - Keywords or search terms + - Filters or criteria mentioned + 4. Use only the parameters that have concrete values from the query + 5. Leave optional parameters as null if not specified + + QUERY PARAMETER EXPLANATION: + The 'query' parameter in the about_judges tool is a flexible search field that accepts: + - Full names or surnames of judges (e.g., "AIBEKOVÁ", "Novotný", "Mária Kováčová") + - Partial names (e.g., "kov" will match Kováč, Kováčová, etc.) + - Any search term that might appear in judge records + - Keywords related to judge specialization or position + - The search is case-insensitive and supports partial matching + + QUERY ANALYSIS EXAMPLES: + - "Hľadaj sudcu Novotný" → judge with query="Novotný" + - "Koľko je sudcov v Košickom kraje?" → judge with krajFacetFilter=["Košický kraj"], size=1 + - "Aktívni sudcovia v Bratislave" → judge with krajFacetFilter=["Bratislavský kraj"], stavZapisuFacetFilter=["active"] + - "Sudcovia so špecializáciou na obchodné právo" → judge with query="obchodné právo" + - "Hľadám sudcu pomenovaný Peter" → judge with query="Peter" + - "Informácie o sudcoch s priezviskom začína na 'K'" → judge with query="K" (partial search) + + RESPONSE FORMATTING: + 1. Summarize what you searched for and which parameters were used + 2. Present the key findings from the tool response + 3. Note any limitations or assumptions + 4. If no results found, suggest alternative search strategies + 5. Always cite that your information comes from the Ministry of Justice API + + CRITICAL RULES: + - For name searches, ALWAYS use the 'query' parameter with the extracted name + - For location-based searches, use 'krajFacetFilter' with exact Slovak region names + - For combined searches (name + location), use both 'query' and 'krajFacetFilter' + - If searching for count/quantity, set size=1 to get only metadata with total count + - ALWAYS verify that extracted parameters match the tool's expected types + - IF insufficient information is provided, ask clarifying questions +""" \ No newline at end of file diff --git a/core/tools/obcianPojednavania.py b/core/tools/obcianPojednavania.py deleted file mode 100644 index ddb8a64..0000000 --- a/core/tools/obcianPojednavania.py +++ /dev/null @@ -1,137 +0,0 @@ -import requests -from pydantic import BaseModel, conint -from typing import Optional, List -from enum import Enum - -from agents import function_tool - -API_BASE_URL = "https://obcan.justice.sk/pilot/api/ress-isu-service" - -class SortDirection(str, Enum): - ASC = "ASC" - DESC = "DESC" - -class CivilProceedingAPI: - - class CivilProceedParams(BaseModel): - query: Optional[str] = None - typSuduFacetFilter: Optional[List[str]] = None - krajFacetFilter: Optional[List[str]] = None - okresFacetFilter: Optional[List[str]] = None - usekFacetFilter: Optional[List[str]] = None - formaUkonuFacetFilter: Optional[List[str]] = None - pojednavaniaOd: Optional[str] = None - pojednavaniaDo: Optional[str] = None - guidSudca: Optional[str] = None - guidSud: Optional[str] = None - spisovaZnacka: Optional[str] = None - verejneVyhlasenie: Optional[bool] = None - indexDatumOd: Optional[str] = None - indexDatumDo: Optional[str] = None - sortProperty: Optional[str] = None - sortDirection: SortDirection = SortDirection.ASC - page: int = 0 - size: int = 20 - - @function_tool - def about_civil_proceeding(args: CivilProceedParams) -> dict: - """ - Načítanie zoznamu občianskoprávnych pojednávaní a verejne vyhlásených rozsudkov na základe filtrovacích kritérií - - :param query: Hľadané slovo alebo slovné spojenie, podľa ktorého sa vyhľadávajú občianskoprávne pojednávania. - :param typSuduFacetFilter: Zoznam typov súdov (fazetový filter), napr. ["Okresný súd", "Krajský súd", "Mestský súd"]. - :param krajFacetFilter: Zoznam krajov (fazetový filter), napr. ["Bratislavský kraj", "Košický kraj", "Prešovský kraj"]. - :param okresFacetFilter: Zoznam okresov (fazetový filter), napr. ["Okres Košice I", "Okres Bratislava IV", "Okres Žilina"]. - :param usekFacetFilter: Zoznam úsekov (fazetový filter), napr. ["C", "O", "S"]. - :param formaUkonuFacetFilter: Zoznam foriem úkonu (fazetový filter), napr. ["Pojednávanie bez rozhodnutia", "Pojednávanie a rozhodnutie", - "Verejné vyhlásenie rozsudku"]. - :param pojednavaniaOd: Dátum pojednávania OD (formát: DD.MM.RRRR), napr. "01.01.2025". - :param pojednavaniaDo: Dátum pojednávania DO (formát: DD.MM.RRRR), napr. "31.12.2025". - :param guidSudca: Identifikátor sudcu pre filtrovanie pojednávaní konkrétneho sudcu, napr. "sudca_2442". - :param guidSud: Identifikátor súdu pre filtrovanie pojednávaní konkrétneho súdu, napr. "sud_135". - :param spisovaZnacka: Spisová značka pojednávania, napr. "30P/1/2025". - :param verejneVyhlasenie: Príznak, či zahrnúť len verejne vyhlásené rozsudky. Hodnota typu boolean. - :param indexDatumOd: Dátum indexácie OD (formát: DD.MM.RRRR), napr. "01.01.2025". - :param indexDatumDo: Dátum indexácie DO (formát: DD.MM.RRRR), napr. "31.12.2025". - :param sortProperty: Názov atribútu, podľa ktorého sa majú záznamy zoradiť, napr. "datumPojednavania", "spisovaZnacka". - :param sortDirection: Smer zoradenia záznamov. Možnosti: "ASC" (predvolené) alebo "DESC". - :param page: Číslo stránky (0 = prvá stránka) pre stránkovanie výsledkov. - :param size: Počet záznamov na stránku (predvolené 20) pre stránkovanie výsledkov. - - :return: Slovník (JSON) obsahujúci zoznam občianskoprávnych pojednávaní a verejne vyhlásených rozsudkov s detailnými informáciami, metadátami a filtrami. - """ - - try: - url = f"{API_BASE_URL}/v1/obcianPojednavania" - response = requests.get(url, params=args.model_dump()) - response.raise_for_status() - - if response.status_code == 200: - data = response.json() - print(f"❗🔨\n {data}") - return {"success": True, "data": data} - else: - return {"success": False, "error": f"Unexpected status code: {response.status_code} ⚠️"} - - except Exception as e: - return {"success": False, "error": f"Error get contract details: {str(e)} 🛑"} - - @function_tool - def civil_proceeding_id(self, id: str) -> dict: - """ - Načítanie detailu občianskoprávneho pojednávania na základe identifikátora. - - :param id: Identifikátor sudcu (povinný parameter), napr. "sudca_123", "sudca_456". - - :return: Slovník (JSON) obsahujúci detailné informácie o občianskoprávnom pojednávaní na základe identifikátora. - """ - try: - url = f"{API_BASE_URL}/v1/obcianPojednavania/{id}" - response = requests.get(url) - response.raise_for_status() - - if response.status_code == 200: - data = response.json() - print(f"⭕🔨\n {data}") - return {"success": True, "data": data} - else: - return {"success": False, "error": f"Unexpected status code: {response.status_code} ⚠️"} - - except Exception as e: - return {"success": False, "error": f"Error : {str(e)} 🛑"} - - class CivilProceedAutocomplete(BaseModel): - query: Optional[str] = None - guidSud: Optional[str] = None - giudSud: Optional[str] = None - verejneVyhlasenie: Optional[bool] = None - limit: Optional[conint(ge=0)] = None - - @function_tool - def civil_proceeding_autocomplete(self, args: CivilProceedAutocomplete) -> dict: - """ - Autocomplete služba pre vyhľadávanie občianskoprávnych pojednávaní a verejne vyhlásených rozsudkov. - - :param query: Hľadané slovo alebo slovné spojenie pre vyhľadávanie pojednávaní. - :param guidSud: Identifikátor súdu pre filtrovanie pojednávaní konkrétneho súdu. - :param giudSud: Duplicitný parameter - pravdepodobne chyba, použite guidSud. - :param verejneVyhlasenie: Príznak, či zahrnúť len verejne vyhlásené rozsudky. - :param limit: Maximálny počet návrhov (0 = všetky možné návrhy). - - :return: Slovník (JSON) obsahujúci zoznam návrhov pre autocomplete. - """ - - try: - url = f"{API_BASE_URL}/v1/obcianPojednavania/autocomplete" - response = requests.get(url, args.model_dump()) - response.raise_for_status() - - if response.status_code == 200: - data = response.json() - print(f"📛🔨\n {data}") - return {"success": True, "data": data} - else: - return {"success": False, "error": f"Unexpected status code: {response.status_code} ⚠️"} - - except Exception as e: - return {"success": False, "error": f"Error : {str(e)} 🛑"} \ No newline at end of file diff --git a/core/tools/rozhodnutie.py b/core/tools/rozhodnutie.py deleted file mode 100644 index cf05090..0000000 --- a/core/tools/rozhodnutie.py +++ /dev/null @@ -1,141 +0,0 @@ -import requests -from pydantic import BaseModel, conint -from typing import Optional, List -from enum import Enum - -from agents import function_tool - -API_BASE_URL = "https://obcan.justice.sk/pilot/api/ress-isu-service" - -class SortDirection(str, Enum): - ASC = "ASC" - DESC = "DESC" - -class DecisionAPI: - - class AboutDecision(BaseModel): - query: Optional[str] = None - typSuduFacetFilter: Optional[List[str]] = None - krajFacetFilter: Optional[List[str]] = None - okresFacetFilter: Optional[List[str]] = None - odkazovanePredpisy: Optional[str] = None - oblastPravnejUpravyFacetFilter: Optional[List[str]] = None - podOblastPravnejUpravyFacetFilter: Optional[List[str]] = None - formaRozhodnutiaFacetFilter: Optional[List[str]] = None - povahaRozhodnutiaFacetFilter: Optional[str] = None - vydaniaOd: Optional[str] = None - vydaniaDo: Optional[str] = None - ecli: Optional[str] = None - spisovaZnacka: Optional[str] = None - cisloSpisu: Optional[str] = None - guidSudca: Optional[str] = None - guidSud: Optional[str] = None - indexDatumOd: Optional[str] = None - indexDatumDo: Optional[str] = None - sortProperty: Optional[str] = None - sortDirection: SortDirection = SortDirection.ASC - page: Optional[int] = None - size : conint(ge=0) = 20 - - @function_tool - def about_decision(self, args: AboutDecision) -> dict: - """ - Načítanie zoznamu rozhodnutí na základe filtrovacích kritérií - - :param query: Hľadané slovo alebo slovné spojenie, podľa ktorého sa vyhľadávajú rozhodnutia. - :param typSuduFacetFilter: Zoznam typov súdov (fazetový filter), napr. ["Okresný súd", "Krajský súd", "Mestský súd"]. - :param krajFacetFilter: Zoznam krajov (fazetový filter), napr. ["Košický kraj", "Bratislavský kraj", "Banskobystrický kraj"]. - :param okresFacetFilter: Zoznam okresov (fazetový filter), napr. ["Okres Banská Bystrica", "Okres Košice I", "Okres Bratislava I"]. - :param odkazovanePredpisy: Odkazované predpisy, na ktoré sa rozhodnutie odvoláva. - :param oblastPravnejUpravyFacetFilter: Zoznam oblastí právnej úpravy (fazetový filter), napr. ["Občianske právo", - "Rodinné právo", "Obchodné právo"]. - :param podOblastPravnejUpravyFacetFilter: Zoznam podoblastí právnej úpravy - (fazetový filter), napr. ["Exekúcia a výkon rozhodnutí", - "Spotrebiteľské zmluvy", "Vyživovacie povinnosti"]. - :param formaRozhodnutiaFacetFilter: Zoznam foriem rozhodnutia (fazetový filter), napr. ["Uznesenie", "Rozsudok", "Platobný rozkaz"]. - :param povahaRozhodnutiaFacetFilter: Povaha rozhodnutia, napr. "Prvostupňové nenapadnuté opravnými prostriedkami". - :param vydaniaOd: Dátum vydania OD (formát: DD.MM.RRRR), napr. "01.01.2020". - :param vydaniaDo: Dátum vydania DO (formát: DD.MM.RRRR), napr. "31.12.2025". - :param ecli: ECLI identifikátor rozhodnutia. - :param spisovaZnacka: Spisová značka rozhodnutia, napr. "4T/20/2014". - :param cisloSpisu: Identifikačné číslo spisu. - :param guidSudca: Identifikátor sudcu pre filtrovanie rozhodnutí konkrétneho sudcu, napr. "sudca_1600". - :param guidSud: Identifikátor súdu pre filtrovanie rozhodnutí konkrétneho súdu, napr. "sud_156". - :param indexDatumOd: Dátum indexácie OD (formát: DD.MM.RRRR), napr. "01.01.2025". - :param indexDatumDo: Dátum indexácie DO (formát: DD.MM.RRRR), napr. "31.12.2025". - :param sortProperty: Názov atribútu, podľa ktorého sa majú záznamy zoradiť, napr. "datumVydania", "spisovaZnacka". - :param sortDirection: Smer zoradenia záznamov. Možnosti: "ASC" (predvolené) alebo "DESC". - :param page: Číslo stránky (0 = prvá stránka) pre stránkovanie výsledkov. - :param size: Počet záznamov na stránku (predvolené 20) pre stránkovanie výsledkov. - - :return: Slovník (JSON) obsahujúci zoznam rozhodnutí s detailnými informáciami, metadátami a filtrami. - """ - try: - url = f"{API_BASE_URL}/v1/rozhodnutie" - response = requests.get(url, params=args.model_dump()) - response.raise_for_status() - - if response.status_code == 200: - data = response.json() - print(f"⭕📃\n {data}") - return {"success": True, "data": data} - else: - return {"success": False, "error": f"Unexpected status code: {response.status_code} ⚠️"} - - except Exception as e: - return {"success": False, "error": f"Error : {str(e)} 🛑"} - - @function_tool - def decision_id(self, id: str) -> dict: - """ - Načítanie rozhodnutia na základe id - - :param id: Identifikátor sudu (povinný parameter), napr. "sud_123", "sud_456". - - :return: Slovník (JSON) obsahujúci detailné informácie o rozhodnutií na základe id - """ - try: - url = f"{API_BASE_URL}/v1/rozhodnutie/{id}" - response = requests.get(url) - response.raise_for_status() - - if response.status_code == 200: - data = response.json() - print(f"⛔📃\n {data}") - return {"success": True, "data": data} - else: - return {"success": False, "error": f"Unexpected status code: {response.status_code} ⚠️"} - - except Exception as e: - return {"success": False, "error": f"Error : {str(e)} 🛑"} - - class DecisionAutocomplete(BaseModel): - query: Optional[str] = None - guidSud: Optional[str] = None - limit: Optional[conint(ge=0)] = None - - @function_tool - def decision_autocomplete(self, args: DecisionAutocomplete) -> dict: - """ - Autocomplete služba pre načítanie rozhodnutia. - - :param query: Hľadané slovo alebo slovné spojenie - :param guidSud: Identifikátor súdu, napr. "sud_123", "sud_456". - :param limit: Maximálny počet rozhodnutie, ktoré sa majú vrátiť. - - :return: Slovník (JSON) obsahujúci zoznam rozhodnutie pre autocomplete. - """ - try: - url = f"{API_BASE_URL}/v1/rozhodnutie/autocomplete" - response = requests.get(url, params=args.model_dump()) - response.raise_for_status() - - if response.status_code == 200: - data = response.json() - print(f"📛📃\n {data}") - return {"success": True, "data": data } - else: - return { "success": False, "error": f"Unexpected status code: {response.status_code} ⚠️"} - - except Exception as e: - return { "success": False, "error": f"Error get contract details: {str(e)} 🛑" } \ No newline at end of file diff --git a/core/tools/spravneKonanie.py b/core/tools/spravneKonanie.py deleted file mode 100644 index 2d8a8b7..0000000 --- a/core/tools/spravneKonanie.py +++ /dev/null @@ -1,142 +0,0 @@ -import requests -from pydantic import BaseModel, conint -from typing import List, Optional -from enum import Enum - -from agents import function_tool - -API_BASE_URL = "https://obcan.justice.sk/pilot/api/ress-isu-service" - -class SortDirection(str, Enum): - ASC = "ASC" - DESC = "DESC" - -class AdminProceedAPI: - - class AdminProceed(BaseModel): - query: Optional[str] = None - druhFacetFilter: Optional[List[str]] = None - datumPravoplatnostiOd : Optional[str] = None - datumPravoplatnostiDo : Optional[str] = None - page: Optional[int] = None - size : conint(ge=0) = 20 - sortProperty: Optional[str] = None - sortDirection: SortDirection = SortDirection.ASC - - @function_tool - def about_admin_proceed(self, args: AdminProceed) -> dict: - """ - - :param query: Hľadané slovo alebo slovné spojenie. - :param druhFacetFilter: Zoznam druhov správnych konaní (fazetový filter). - :param datumPravoplatnostiOd: Dátum právoplatnosti OD (formát: DD.MM.RRRR). - Príklad: "15.03.2023", "01.01.2020" - :param datumPravoplatnosiDo: Dátum právoplatnosti DO (formát: DD.MM.RRRR). - Príklad: "15.03.2023", "01.01.2020" - :param page: Číslo stránky (0 = prvá stránka). - Poznámka: Zmena 'page' zobrazí ĎALŠIE konania, nie tie isté. - Príklad: 'page=0' → konania 1-20, 'page=1' → konania 21-40. - :param size: Počet záznamov na stránku (predvolené 20). - Príklad: 'size=10' → 10 konaní na stránke. - :param sortProperty: Atribút pre zoradenie výsledkov. - :param sortDirection: Smer zoradenia (ASC alebo DESC). - - :return: Slovník s výsledkami vyhľadávania správnych konaní. - """ - - try: - url = f"{API_BASE_URL}/v1/spravneKonanie" - response = requests.get(url, params=args.model_dump()) - response.raise_for_status() - - if response.status_code == 200: - data = response.json() - print(f"⭕👨\n {data}") - return {"success": True, "data": data} - else: - return {"success": False, "error": f"Unexpected status code: {response.status_code} ⚠️"} - - except Exception as e: - return {"success": False, "error": f"Error : {str(e)} 🛑"} - - @function_tool - def admin_proceed_id(self, id: str) -> dict: - """ - Načítanie binárneho obsahu prílohy správneho konania na základe ID. - - :param id: Unikátny identifikátor administratívneho konania (povinný parameter). - Príklad: sud_175 - - :return: Slovník (JSON) obsahujúci binárne dáta prílohy a metainformácie. - """ - try: - url = f"{API_BASE_URL}/v1/spravneKonanie/{id}" - response = requests.get(url) - response.raise_for_status() - - if response.status_code == 200: - data = response.json() - print(f"📛👨\n {data}") - return {"success": True, "data": data} - else: - return {"success": False, "error": f"Unexpected status code: {response.status_code} ⚠️"} - - except Exception as e: - return {"success": False, "error": f"Error : {str(e)} 🛑"} - - @function_tool - def admin_proceed_attachments(self, id: str) -> dict: - """ - Načítanie správneho konania na základe id - - :param id: Unikátny identifikátor administratívneho konania (povinný parameter). - Príklad: sud_175 - - :return: Slovník (JSON) obsahujúci detailné informácie o správnom konaní na základe id. - """ - try: - url = f"{API_BASE_URL}/v1/spravneKonanie/priloha/{id}" - response = requests.get(url) - response.raise_for_status() - - if response.status_code == 200: - data = response.json() - print(f"❗👨\n {data}") - return {"success": True, "data": data} - else: - return {"success": False, "error": f"Unexpected status code: {response.status_code} ⚠️"} - - except Exception as e: - return {"success": False, "error": f"Error : {str(e)} 🛑"} - - class AdminProceedAutocomplete(BaseModel): - query: Optional[str] = None - limit: Optional[conint(ge=1)] = None - - @function_tool - def admin_proceed_autocomplete(self, args: AdminProceedAutocomplete) -> dict: - """ - Autocomplete služba pre vyhľadávanie správnych konaní. - - :param query: Hľadané slovo alebo slovné spojenie pre vyhľadávanie správnych konaní. - - :param limit: Maximálny počet návrhov, ktoré sa majú vrátiť. - None → API vráti 5 dokumentov (predvolená hodnota). - Hodnota 0 spôsobí chybu API, preto použite None namiesto 0 - - :return: Slovník (JSON) obsahujúci zoznam návrhov pre autocomplete. - """ - try: - url = f"{API_BASE_URL}/v1/spravneKonanie/autocomplete" - response = requests.get(url, args.model_dump()) - response.raise_for_status() - - if response.status_code == 200: - data = response.json() - print(f"⭕\n {data}") - return {"success": True, "data": data} - else: - return {"success": False, "error": f"Unexpected status code: {response.status_code} ⚠️"} - - except Exception as e: - return {"success": False, "error": f"Error : {str(e)} 🛑"} \ No newline at end of file diff --git a/core/tools/sud.py b/core/tools/sud.py deleted file mode 100644 index 941e0a4..0000000 --- a/core/tools/sud.py +++ /dev/null @@ -1,114 +0,0 @@ -import requests -from pydantic import BaseModel, conint -from typing import List, Optional -from enum import Enum - -from agents import function_tool - -API_BASE_URL = "https://obcan.justice.sk/pilot/api/ress-isu-service" - -class SortDirection(str, Enum): - ASC = "ASC" - DESC = "DESC" - -class CourtAPI: - - class ListCourts(BaseModel): - query: Optional[str] = None - typSuduFacetFilter: List[str] = [] - krajFacetFilter: List[str] = [] - zahrnutZaniknuteSudy: Optional[bool] = None - sortProperty: Optional[str] = None - sortDirection: SortDirection = SortDirection.ASC - - - @function_tool - def about_courts(args: ListCourts) -> dict: - """ - Načítanie zoznamu súdov na základe filtrovacích kritérii - - :param query: Hľadané slovo alebo slovné spojenie, podľa ktorého sa vyhľadávajú súdy. - :param typSuduFacetFilter: Zoznam typov súdov (fazetový filter), napr. ["Okresný súd", "Krajský súd"]. - :param krajFacetFilter: Zoznam krajov (fazetový filter), napr. ["Bratislavský kraj", "Košický kraj"]. - :param zahrnutZaniknuteSudy: Príznak, či zahrnúť aj zaniknuté súdy. Hodnota typu boolean. - :param sortProperty: Názov atribútu, podľa ktorého sa majú záznamy zoradiť. - :param sortDirection: Smer zoradenia záznamov. Možnosti: "ASC" (predvolené) alebo "DESC". - - - :return: Slovník (JSON) obsahujúci detailné informácie s detailnými informáciami, metadátami a filtrami. - """ - try: - url = f"{API_BASE_URL}/v1/sud" - response = requests.get(url, params=args.model_dump()) - response.raise_for_status() - - if response.status_code == 200: - data = response.json() - print(f"⭕🏛️\n {data}") - return {"success": True, "data": data} - else: - return {"success": False, "error": f"Unexpected status code: {response.status_code} ⚠️"} - - except Exception as e: - return {"success": False, "error": f"Error get contract details: {str(e)} 🛑"} - - - class CourtDetail(BaseModel): - idSudu: Optional[str] = None - - - @function_tool - def get_court(args: CourtDetail) -> dict: - """ - Načítanie detailnej informácie o súde na základe jeho ID. - - :param idSudu: Identifikátor súdu. - - :return: Slovník (JSON) obsahujúci detailné informácie sudov. - """ - try: - url = f"{API_BASE_URL}/v1/sud/{args.idSudu}" - response = requests.get(url) - response.raise_for_status() - - if response.status_code == 200: - data = response.json() - data.pop("foto", None) - print(f"❗🏛️\n {data}") - return {"success": True, "data": data} - else: - return {"success": False, "error": f"Unexpected status code: {response.status_code} ⚠️"} - - except Exception as e: - return {"success": False, "error": f"Error get contract details: {str(e)} 🛑"} - - class CourtAutocomplete(BaseModel): - query: Optional[str] = None - limit: Optional[conint(ge=0)] = None - - - @function_tool - def court_autocomplete(args: CourtAutocomplete) -> dict: - """ - Autocomplete pre vyhľadávanie súdu. - - :param query: Hľadané slovo alebo slovné spojenie, podľa ktorého sa majú hľadať súdy. - :param limit: Maximálny počet návrhov súdov, ktoré sa majú vrátiť. Ak je 0, vráti všetky možné návrhy. - - :return: Slovník (JSON) obsahujúci zoznam návrhov súdov pre autocomplete. - """ - - try: - url = f"{API_BASE_URL}/v1/sud/autocomplete" - response = requests.get(url, params=args.model_dump()) - response.raise_for_status() - - if response.status_code == 200: - data = response.json() - print(f"📛🏛️\n {data}") - return {"success": True, "data": data } - else: - return { "success": False, "error": f"Unexpected status code: {response.status_code} ⚠️"} - - except Exception as e: - return { "success": False, "error": f"Error get contract details: {str(e)} 🛑" } \ No newline at end of file diff --git a/core/tools/sudca.py b/core/tools/sudca.py deleted file mode 100644 index cbd2de5..0000000 --- a/core/tools/sudca.py +++ /dev/null @@ -1,126 +0,0 @@ -import requests -from pydantic import BaseModel, conint -from typing import List, Optional -from enum import Enum - -from agents import function_tool - -API_BASE_URL = "https://obcan.justice.sk/pilot/api/ress-isu-service" - -class SortDirection(str, Enum): - ASC = "ASC" - DESC = "DESC" - -class JudgeAPI: - - class JudgeParams(BaseModel): - query: Optional[str] = None - funkciaFacetFilter: Optional[List[str]] = None - typSuduFacetFilter: Optional[List[str]] = None - krajFacetFilter: Optional[List[str]] = None - okresFacetFilter: Optional[List[str]] = None - stavZapisuFacetFilter: Optional[List[str]] = None - guidSud: Optional[str] = None - page: Optional[int] = None - size: Optional[conint(ge=0)] = None - sortProperty: Optional[str] = None - sortDirection: SortDirection = SortDirection.ASC - - @function_tool - def about_judge(self, args: JudgeParams): - """ - Načítanie zoznamu sudcov na základe filtrovacích kritérii - - :param query: Hľadané slovo alebo slovné spojenie pre vyhľadávanie sudcov. - :param funkciaFacetFilter: Zoznam funkcií sudcov: ["Sudca", "Predseda", "Podpredseda", "Hosťujúci sudca", "a ine"]. - :param typSuduFacetFilter: Zoznam typov súdov: ["Okresný súd", "Krajský súd", "Mestský súd", - "Najvyšší súd SR", "Správny súd", - "Špecializovaný trestný súd"]. - :param krajFacetFilter: Zoznam krajov: ["Bratislavský kraj", "Košický kraj", "Banskobystrický kraj", - "Prešovský kraj", "Žilinský kraj", "Trnavský kraj", "Nitriansky kraj", - "Trenčiansky kraj"]. - :param okresFacetFilter: Zoznam okresov: ["Okres [mesto Slovenska]"] napr. "Okres Bratislava I", "Okres Košice I". - :param stavZapisuFacetFilter: Zoznam stavov zápisu: ["prerusenie vykonu - poberatel", "aktivity", - "odvolany", "vymazany", "prerusenie vykonu - ina funkce"]. - :param guidSud: Identifikátor súdu pre filtrovanie sudcov konkrétneho súdu, napr. "sud_101". - :param page: Číslo stránky (0 = prvá stránka) pre stránkovanie výsledkov. - :param size: Počet záznamov na stránku (predvolené 20) pre stránkovanie výsledkov. - :param sortProperty: Atribút pre zoradenie výsledkov, napr. "priezvisko", "meno". - :param sortDirection: Smer zoradenia záznamov: "ASC" (predvolené) alebo "DESC". - - :return: Slovník (JSON) obsahujúci zoznam sudcov s detailnými informáciami, metadátami a filtrami. - - :return: Slovník (JSON) obsahujúci zoznam súdov na základe filtrovacích kritérii - """ - try: - url = f"{API_BASE_URL}/v1/sudca" - response = requests.get(url, params=args.model_dump()) - response.raise_for_status() - - if response.status_code == 200: - data = response.json() - print(f"📛🧑‍⚖️\n {data}") - return {"success": True, "data": data} - else: - return {"success": False, "error": f"Unexpected status code: {response.status_code} ⚠️"} - - except Exception as e: - return {"success": False, "error": f"Error : {str(e)} 🛑"} - - @function_tool - def judge_id(self, id: str) -> dict: - """ - Načítanie detailu sudcu na základe identifikátora. - - :param id: Identifikátor sudcu (povinný parameter), napr. "sudca_123", "sudca_456". - - :return: Slovník (JSON) obsahujúci detailné informácie o sudcovi na základe identifikátora. - """ - try: - url = f"{API_BASE_URL}/v1/sudca/{id}" - response = requests.get(url) - response.raise_for_status() - - if response.status_code == 200: - data = response.json() - print(f"⛔🧑‍⚖️\n {data}") - return {"success": True, "data": data} - else: - return {"success": False, "error": f"Unexpected status code: {response.status_code} ⚠️"} - - except Exception as e: - return {"success": False, "error": f"Error : {str(e)} 🛑"} - - class JudgeAutocomplete(BaseModel): - query: Optional[str] = None - guidSud: Optional[str] = None - limit: Optional[conint(ge=1)] = None - - @function_tool - def judge_autocomplete(self, args: JudgeAutocomplete) -> dict: - """ - Autocomplete služba pre vyhľadávanie sudcov. - - :param query: Hľadané slovo alebo slovné spojenie. - :param guidSud: Identifikátor súdu pre filtrovanie sudcov konkrétneho súdu. - Príklad: "sud_175" - :param limit: Maximálny počet návrhov, ktoré sa majú vrátiť. - None → API vráti 5 dokumentov (predvolená hodnota). - Hodnota 0 spôsobí chybu API, preto použite None namiesto 0 - - :return: Slovník (JSON) obsahujúci zoznam návrhov sudcov pre autocomplete. - """ - try: - url = f"{API_BASE_URL}/v1/sudca/autocomplete" - response = requests.get(url, args.model_dump()) - response.raise_for_status() - - if response.status_code == 200: - data = response.json() - print(f"⭕🧑‍⚖️\n {data}") - return {"success": True, "data": data} - else: - return {"success": False, "error": f"Unexpected status code: {response.status_code} ⚠️"} - - except Exception as e: - return {"success": False, "error": f"Error : {str(e)} 🛑"} \ No newline at end of file diff --git a/core/tools/zmluvy.py b/core/tools/zmluvy.py deleted file mode 100644 index 89f7822..0000000 --- a/core/tools/zmluvy.py +++ /dev/null @@ -1,121 +0,0 @@ -import requests -from pydantic import BaseModel, conint -from typing import List, Optional -from enum import Enum - -from agents import function_tool - -API_BASE_URL = "https://obcan.justice.sk/pilot/api/ress-isu-service" - - -class SortDirection(str, Enum): - ASC = "ASC" - DESC = "DESC" - -class ContractsAPI: - - class ContractsList(BaseModel): - query : Optional[str] = None - typDokumentuFacetFilter: Optional[List[str]] = None - odberatelFacetFilter: Optional[List[str]] = None - dodavatelFacetFilter: Optional[List[str]] = None - hodnotaZmluvyFacetFilter: Optional[List[str]] = None - guidSud: Optional[str] = None - sortProperty: Optional[str] = None - sortDirection: SortDirection = SortDirection.ASC - page: Optional[int] = None - size : conint(ge=0) = 20 - - @function_tool - def about_contracts(args: ContractsList) -> dict: - """ - Načítanie zoznamu zmlúv podľa zadaných filtrov. - - :param query: Hľadaný výraz, podľa ktorého sa vyhľadávajú zmluvy. - :param typDokumentuFacetFilter: Typy dokumentov ako fazetový filter (napr. ["ZMLUVA","FAKTURA"]). - :param odberatelFacetFilter: Odberatelia pre fazetový filter. - :param dodavatelFacetFilter: Dodávatelia pre fazetový filter. - :param hodnotaZmluvyFacetFilter: Hodnoty zmlúv (filtrovacie intervaly). - :param guidSud: Identifikátor súdu (napr. "sud_101"). - :param sortProperty: Atribút na triedenie výsledkov. - :param sortDirection: ASC alebo DESC. - :param page: Číslo strany (0 = prvá strana). - :param size: Počet výsledkov na strane. - - :return: JSON so zoznamom zmlúv a metadátami. - """ - try: - url = f"{API_BASE_URL}/v1/zmluvy" - response = requests.get(url, params=args.model_dump()) - response.raise_for_status() - - if response.status_code == 200: - data = response.json() - print(f"⭕🖇️\n {data}") - return {"success": True, "data": data} - else: - return {"success": False, "error": f"Unexpected status code: {response.status_code} ⚠️"} - - except Exception as e: - return {"success": False, "error": f"Error get contract details: {str(e)} 🛑"} - - class ContractDetail(BaseModel): - idZmluvy: str - - @function_tool - def get_contract(args: ContractDetail) -> dict: - """ - Načítanie detailu zmluvy podľa jej identifikátora. - - :param idZmluvy: Jedinečný identifikátor zmluvy. - - :return: JSON slovník obsahujúci detailné informácie o zmluve. - """ - try: - url = f"{API_BASE_URL}/v1/zmluvy/{args.idZmluvy}" - response = requests.get(url) - response.raise_for_status() - - if response.status_code == 200: - data = response.json() - print(f"⛔🖇️\n {data}") - return {"success": True, "data": data } - else: - return { "success": False, "error": f"Unexpected status code: {response.status_code} ⚠️"} - - except Exception as e: - return { "success": False, "error": f"Error get contract details: {str(e)} 🛑" } - - class ContractsAutocomplete(BaseModel): - query : Optional[str] = None - guidSud: Optional[str] = None - limit: Optional[conint(ge=1)] = None - - @function_tool - def contracts_autocomplete(args: ContractsAutocomplete) -> dict: - """ - Autocomplete pre vyhľadávanie zmlúv. - - :param query: Hľadaný text alebo výraz na vyhľadanie zmlúv. - :param guidSud: Identifikátor súdu (napr. "sud_101") na filtrovanie zmlúv konkrétneho súdu. - :param limit: Maximálny počet výsledkov. - None = predvolených 5 výsledkov. - Hodnota 0 spôsobí chybu API — použite radšej None. - - :return: JSON slovník obsahujúci zoznam návrhov zmlúv pre autocomplete. - """ - - try: - url = f"{API_BASE_URL}/v1/zmluvy/autocomplete" - response = requests.get(url, params=args.model_dump()) - response.raise_for_status() - - if response.status_code == 200: - data = response.json() - print(f"📛🖇️\n {data}") - return {"success": True, "data": data} - else: - return {"success": False, "error": f"Unexpected status code: {response.status_code} ⚠️"} - - except Exception as e: - return {"success": False, "error": f"Error get contract details: {str(e)} 🛑"} diff --git a/requirements.txt b/requirements.txt index 3d3ef92..4e07b8a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,6 @@ openai-agents python-dotenv streamlit -requests \ No newline at end of file +requests +pydantic +httpx \ No newline at end of file