"""Defines the AI agent and logic for medical materials generation.This module contains the core components for generating lists of necessarymaterials for medical simulations. It leverages agno's structured outputto ensure the generated list of materials is correctly formatted and validated.Version: 3.2"""importosimportloggingimportsqlite3fromtypingimportList,Dict,Anyfromagno.agentimportAgent,RunResponsefromfastapiimportHTTPExceptionfrommodelsimportMATModelRequest,MATModelResponse,MatModelListResponsefromutilsimportget_small_modelfromconfigimportDATABASE_PATHlogger=logging.getLogger(__name__)materials_agent=Agent(name="Medical Materials Generator",role="An expert medical educator and simulation specialist who generates comprehensive lists of necessary materials for medical simulation scenarios, with general-purpose descriptions.",model=get_small_model(),response_model=MatModelListResponse,instructions=["Your task is to generate a comprehensive list of necessary materials for a medical simulation scenario.","All text content for 'nome' and 'descrizione' must be in **Italian**.","The materials must be realistic and appropriate for the described scenario, patient type, and target audience.","PRIORITY: If a material from the provided database list is suitable for the scenario, you MUST use its EXACT name.","For any NEW material you create, provide a clear, specific Italian name and a GENERAL-PURPOSE description.","The description should explain the material's main function in a way that is reusable for other scenarios. It must NOT be specific to the current scenario.","Pay attention to the objective examination findings (esame_obiettivo) to determine WHICH materials are needed, but keep their descriptions generic.","Consider the target audience (students, nurses, specialists) to adjust the complexity and type of materials selected.",])
[docs]defcreate_materials_prompt(request:MATModelRequest,existing_materials:List[Dict[str,Any]])->str:"""Creates the simplified prompt for the materials generation agent."""existing_materials_text=""ifexisting_materials:existing_materials_text="\n\n## DATABASE MATERIALS\n"existing_materials_text+="Here is a list of materials already available in the database. If any of these are appropriate, you MUST use their exact 'nome'.\n"formaterialinexisting_materials:existing_materials_text+=f"- {material['nome']}\n"returnf""" Generate a comprehensive list of necessary materials for the following medical simulation. ## SCENARIO CONTEXT - Patient Type: {request.tipologia_paziente} - Scenario Description: {request.descrizione_scenario} - Target Audience: {request.target} - Objective Examination: {request.esame_obiettivo}{existing_materials_text} ## INSTRUCTIONS 1. Generate a list of materials needed for this simulation. 2. All names ('nome') and descriptions ('descrizione') must be in Italian. 3. If a material from the database list fits, use its exact name. 4. For new materials, create a specific Italian name. 5. CRITICAL: The description for EACH material must be GENERAL and REUSABLE for a database. Do not mention the specifics of this scenario in the description. """
[docs]defgenerate_materials(request:MATModelRequest)->List[MATModelResponse]:"""Generates a list of materials for a medical simulation scenario."""logger.info(f"Received request to generate materials for: {request.tipologia_paziente} - Target: {request.target}")try:existing_materials=get_existing_materials()logger.info(f"Retrieved {len(existing_materials)} existing materials from database")prompt=create_materials_prompt(request,existing_materials)run_response:RunResponse=materials_agent.run(prompt)# type: ignorevalidated_response=run_response.contentifnotisinstance(validated_response,MatModelListResponse):raiseTypeError(f"Agent returned unexpected type: {type(validated_response)}. Expected MatModelListResponse.")validated_materials=validated_response.materialslogger.info(f"Successfully generated {len(validated_materials)} materials")returnvalidated_materialsexceptExceptionase:logger.error(f"An unexpected error occurred during material generation: {e}",exc_info=True)raiseHTTPException(status_code=500,detail={"error":"Failed to generate valid materials","message":str(e)})
[docs]defget_existing_materials()->List[Dict[str,Any]]:"""Retrieves all existing materials from the SQLite database."""db_path=DATABASE_PATHifnotos.path.exists(db_path):logger.warning(f"Database not found at {db_path}, returning no existing materials.")return[]try:conn=sqlite3.connect(db_path)conn.row_factory=sqlite3.Rowcursor=conn.cursor()cursor.execute("SELECT id_materiale, nome, descrizione FROM Materiale")materials=[dict(row)forrowincursor.fetchall()]conn.close()logger.debug(f"Found {len(materials)} materials in the database.")returnmaterialsexceptsqlite3.Errorase:logger.error(f"Database error while querying materials: {e}",exc_info=True)return[]exceptExceptionase:logger.error(f"An unexpected error occurred while getting materials from DB: {e}",exc_info=True)return[]