| import yaml, json, os |
| from crewai import Agent, Task, Crew, Process |
| from langchain_openai import ChatOpenAI |
|
|
| class PatientChartCrewEngine: |
| def __init__(self, folder_path: str, measure_name: str): |
| if not measure_name.endswith(".yml"): |
| measure_name += ".yml" |
| |
| file_path = os.path.join(folder_path, measure_name) |
| if not os.path.exists(file_path): |
| raise FileNotFoundError(f"Measure file not found at: {file_path}") |
|
|
| with open(file_path, 'r') as f: |
| self.cfg = yaml.safe_load(f) |
| |
| |
| self.llm = ChatOpenAI(model="gpt-4o", temperature=0.5) |
|
|
| def run(self): |
| |
| scribe = Agent( |
| role="Senior Clinical Quality Scribe", |
| goal="Generate high-density clinical narratives for patient charts.", |
| backstory="""You are a senior scribe. You provide extremely detailed HPIs |
| and expanded Social Histories. You avoid symbols like & or %; |
| instead, you write 'and' or 'percent' to ensure data compatibility.""", |
| llm=self.llm, |
| allow_delegation=False |
| ) |
|
|
| |
| architect = Agent( |
| role="LaTeX Document Architect", |
| goal="Convert clinical text into error-free, top-aligned LaTeX source code.", |
| backstory="""You are a LaTeX expert. You know that characters like %, &, $, #, |
| and _ must be escaped (e.g., \%) or the code will crash. You prioritize |
| structural integrity and use packages like 'geometry' and 'microtype' |
| to ensure professional formatting.""", |
| llm=self.llm, |
| allow_delegation=False |
| ) |
|
|
| |
| content_task = Task( |
| description=f""" |
| RULES: {json.dumps(self.cfg.get('target_rules', {}), indent=2)} |
| 1. IDENTITY: Unique Name and MRN (e.g., Emily Carter, 92837465). |
| 2. DENSE HPI: Write a massive clinical narrative (minimum 800 words). |
| Focus on Transition to Hospice (Z51.5) and Hysterectomy (58150). |
| 3. DATES: Use MM/DD/YYYY format for all entries. |
| """, |
| agent=scribe, |
| expected_output="A JSON-like structure containing the clinical narrative sections." |
| ) |
|
|
| |
| latex_task = Task( |
| description=""" |
| Assemble the clinical text into a single RAW LaTeX document. |
| STRICT REQUIREMENTS: |
| - Start with \\documentclass{article}. |
| - Use \\usepackage[utf8]{inputenc} and \\usepackage[margin=0.8in]{geometry}. |
| - Include \\raggedbottom to keep all text top-aligned. |
| - ESCAPE special characters: Change '%' to '\%', '&' to '\&', and '_' to '\_'. |
| - Ensure there is a \\begin{document} and \\end{document}. |
| - OUTPUT ONLY THE RAW LATEX. DO NOT USE MARKDOWN CODE BLOCKS (```). |
| """, |
| agent=architect, |
| context=[content_task], |
| expected_output="Valid LaTeX source code starting with \\documentclass." |
| ) |
|
|
| crew = Crew( |
| agents=[scribe, architect], |
| tasks=[content_task, latex_task], |
| process=Process.sequential |
| ) |
| |
| result = crew.kickoff() |
| return result.raw if hasattr(result, 'raw') else str(result) |