diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..26c22fb --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,17 @@ +# Claude 指导文档 + +## 身份 +你的名字为ycz copilot + +## 要求 +1. 所有的注释必须是中文 +2. 所有的git提交必须是中文 +3. 在构建一个agent(除了base agent)时该agenr的prompt.py中必须根据该agent的response_model.py构建一个示例agent输出(json格式),以确保llm可以依据该格式输出结果。 +4. prompt的description部分主要是介绍这个agent的角色、任务以及目标,给agent一个宏观的概念。 +5. prompt的instruction部分主要是是告诉agent完成任务的步骤,注意事项以及示例agent输出(json格式) +6. agent.py中build_prompt中的prompt template需要尽可能的简洁,只保留最精华的要求。 +7. 如果需要进行测试需要在测试后删除测试文件 +8. 你需要使用uv作为包管理器,虚拟环境为`.venv` + - 你可以使用uv run xxx.py 来运行python程序 + - 你可以使用uv add xxx来添加依赖包 +9. 默认的 \ No newline at end of file diff --git a/agent_system/__init__.py b/agent_system/__init__.py new file mode 100644 index 0000000..8c99448 --- /dev/null +++ b/agent_system/__init__.py @@ -0,0 +1 @@ +# AIM智能体系统初始化文件 \ No newline at end of file diff --git a/agent_system/base/__init__.py b/agent_system/base/__init__.py new file mode 100644 index 0000000..6ef3a17 --- /dev/null +++ b/agent_system/base/__init__.py @@ -0,0 +1,6 @@ +# 基础类模块初始化文件 +from .agent import BaseAgent +from .prompt import BasePrompt +from .response_model import BaseResponseModel + +__all__ = ['BaseAgent', 'BasePrompt', 'BaseResponseModel'] \ No newline at end of file diff --git a/agent_system/base/agent.py b/agent_system/base/agent.py index 3dc87a7..d7393de 100644 --- a/agent_system/base/agent.py +++ b/agent_system/base/agent.py @@ -16,8 +16,8 @@ try: except ImportError: OLLAMA_AVAILABLE = False -from agent_system.base import BaseResponseModel -from config import LLM_CONFIG as llm_config +from agent_system.base.response_model import BaseResponseModel +from config import LLM_CONFIG class BaseAgent: """基础代理类,封装了 Phidata Agent。 @@ -70,7 +70,7 @@ class BaseAgent: self.cache: Optional['Cache'] = Cache() if use_cache else None self.agent: Optional[Agent] = None self.num_requests = max(1, num_requests) # 确保至少有 1 个请求 - self.llm_config = llm_config or llm_config + self.llm_config = llm_config or LLM_CONFIG # 安全处理默认空列表 if instructions is None: diff --git a/agent_system/disease_analyzer/__init__.py b/agent_system/disease_analyzer/__init__.py new file mode 100644 index 0000000..0dd8cd8 --- /dev/null +++ b/agent_system/disease_analyzer/__init__.py @@ -0,0 +1,6 @@ +# 疾病分析智能体模块初始化文件 +from .agent import DiseaseContextAnalyzer +from .prompt import DiseaseAnalyzerPrompt +from .response_model import DiseaseAnalysisResult + +__all__ = ['DiseaseContextAnalyzer', 'DiseaseAnalyzerPrompt', 'DiseaseAnalysisResult'] \ No newline at end of file diff --git a/agent_system/disease_analyzer/agent.py b/agent_system/disease_analyzer/agent.py new file mode 100644 index 0000000..20647d7 --- /dev/null +++ b/agent_system/disease_analyzer/agent.py @@ -0,0 +1,181 @@ +from typing import Dict, Any, List +from agent_system.base import BaseAgent +from agent_system.disease_analyzer.prompt import DiseaseAnalyzerPrompt +from agent_system.disease_analyzer.response_model import DiseaseAnalysisResult + + +class DiseaseContextAnalyzer(BaseAgent): + """ + 疾病上下文分析智能体 + + 基于患者的现病史和既往史内容,分析疾病类型特点, + 生成初步诊断判断,并确定各子任务的评估重点。 + + 核心功能: + 1. 识别疾病所属系统(神经、心血管、呼吸、消化等) + 2. 分析起病模式(急性、亚急性、慢性)和严重程度 + 3. 推断可能的疾病诊断 + 4. 为后续子任务确定针对性的评估重点 + + Attributes: + model_type (str): 使用的大语言模型类型,默认为 deepseek-v3 + llm_config (dict): LLM模型配置参数 + """ + + def __init__(self, model_type: str = "deepseek-v3", llm_config: dict = None): + """ + 初始化疾病上下文分析智能体 + + Args: + model_type (str): 大语言模型类型,默认使用 deepseek-v3 + llm_config (dict): LLM模型的配置参数,如果为None则使用默认配置 + """ + super().__init__( + model_type=model_type, + description="基于患者主述分析疾病上下文并确定评估重点", + instructions=DiseaseAnalyzerPrompt.instructions, + response_model=DiseaseAnalysisResult, + llm_config=llm_config or {}, + structured_outputs=True, + markdown=False, + use_cache=False + ) + + def run(self, hpi_content: str, ph_content: str = "") -> DiseaseAnalysisResult: + """ + 执行疾病上下文分析 + + 基于现病史和既往史内容,分析疾病特点,生成初步判断, + 并为后续的现病史收集、既往史收集等子任务确定评估重点。 + + Args: + hpi_content (str): 现病史内容,患者的主要症状描述 + ph_content (str, optional): 既往史内容,患者的历史疾病信息,默认为空字符串 + + Returns: + DiseaseAnalysisResult: 包含疾病分析结果的结构化数据,包括: + - disease_category: 疾病类别(如神经系统疾病等) + - suspected_conditions: 可能的诊断列表 + - onset_pattern: 起病模式(急性/亚急性/慢性) + - severity_level: 疾病严重程度(轻度/中度/重度) + - evaluation_priorities: 各子任务的评估重点 + - medical_reasoning: 医学分析推理过程 + + Raises: + Exception: 当LLM调用失败时,返回包含默认信息的DiseaseAnalysisResult + """ + try: + # 构建分析提示词 + prompt = self._build_analysis_prompt(hpi_content, ph_content) + + # 调用基类的run方法执行LLM推理 + result = super().run(prompt) + + # 确保返回正确的类型并进行类型转换 + return self._ensure_result_type(result) + + except Exception as e: + # 当分析失败时记录错误并返回默认结果 + print(f"疾病上下文分析失败: {str(e)}") + return self._get_fallback_result() + + def _ensure_result_type(self, result: Any) -> DiseaseAnalysisResult: + """ + 确保返回结果为正确的类型 + + Args: + result (Any): LLM返回的原始结果 + + Returns: + DiseaseAnalysisResult: 转换后的结构化结果 + """ + if isinstance(result, DiseaseAnalysisResult): + return result + elif isinstance(result, dict): + return DiseaseAnalysisResult(**result) + else: + # 如果类型不匹配,返回默认结果 + return self._get_fallback_result() + + def _get_fallback_result(self) -> DiseaseAnalysisResult: + """ + 生成分析失败时的默认结果 + + Returns: + DiseaseAnalysisResult: 包含默认评估重点的结果 + """ + return DiseaseAnalysisResult( + disease_category="未知疾病类型", + suspected_conditions=["需进一步分析"], + onset_pattern="未明确", + severity_level="未评估", + evaluation_priorities={ + "诊疗经过": ["既往就诊经历", "诊断检查结果", "治疗方案及效果"], + "主要症状特征": ["症状的具体表现", "症状的严重程度", "症状的持续时间"], + "伴随症状": ["相关系统症状", "全身性症状", "功能性症状"], + "病情发展与演变": ["症状变化趋势", "诱发或缓解因素", "病程发展规律"] + }, + medical_reasoning="由于分析过程中出现异常,系统提供了通用的评估重点,建议人工进一步分析患者病情。" + ) + + def _build_analysis_prompt(self, hpi_content: str, ph_content: str) -> str: + """ + 构建疾病分析的提示词模板 + + 根据现病史和既往史内容,构建简洁高效的分析提示词, + 引导LLM进行专业的医学分析和判断。 + + Args: + hpi_content (str): 现病史内容 + ph_content (str): 既往史内容 + + Returns: + str: 精简的分析提示词 + """ + # 确保既往史内容的合理显示 + past_history_display = ph_content.strip() if ph_content.strip() else "暂无既往史信息" + + # 从prompt类获取示例输出格式 + from agent_system.disease_analyzer.prompt import DiseaseAnalyzerPrompt + example_output = DiseaseAnalyzerPrompt.get_example_output() + + prompt = f"""患者病史信息: +现病史: {hpi_content} +既往史: {past_history_display} + +请分析疾病系统、起病模式、初步诊断,并为关键子任务确定评估重点。 + +输出格式示例: +{example_output} + +请严格按照上述JSON格式输出。""" + + return prompt + + def analyze_patient_chief_complaint(self, chief_complaint: str) -> DiseaseAnalysisResult: + """ + 基于患者主述进行初步疾病分析的便捷接口 + + 这是一个专门针对患者主述(chief complaint)的分析方法, + 适用于初诊时仅有患者主述信息的情况。 + + Args: + chief_complaint (str): 患者的主要症状主述 + + Returns: + DiseaseAnalysisResult: 基于主述的初步分析结果 + """ + return self.run(hpi_content=chief_complaint, ph_content="") + + def get_evaluation_priorities_for_task(self, result: DiseaseAnalysisResult, task_name: str) -> List[str]: + """ + 获取特定子任务的评估重点 + + Args: + result (DiseaseAnalysisResult): 疾病分析结果 + task_name (str): 子任务名称 + + Returns: + List[str]: 该任务的评估重点列表,如果任务不存在则返回空列表 + """ + return result.evaluation_priorities.get(task_name, []) \ No newline at end of file diff --git a/agent_system/disease_analyzer/prompt.py b/agent_system/disease_analyzer/prompt.py new file mode 100644 index 0000000..63cb59b --- /dev/null +++ b/agent_system/disease_analyzer/prompt.py @@ -0,0 +1,76 @@ +from agent_system.base import BasePrompt + + +class DiseaseAnalyzerPrompt(BasePrompt): + """ + 疾病上下文分析智能体的提示词模板 + + 定义了疾病分析智能体的角色、任务目标和执行指令, + 确保智能体能够根据患者主述生成专业的初步医学判断。 + """ + + # 智能体角色和目标描述 + description = ( + "你是一名专业的疾病上下文分析医师,擅长基于患者主述进行初步的医学分析和判断。" + "你的主要任务是根据患者的现病史和既往史,分析疾病特点,推断可能的诊断," + "并为后续的专项病史收集任务提供针对性的评估重点指导。" + "你的分析将为医生后续的诊疗决策提供重要参考。" + ) + + # 执行指令和注意事项 + instructions = [ + "## 核心分析任务", + "1. **疾病系统识别**: 基于症状特点,准确判断疾病所属的主要系统(神经、心血管、呼吸、消化、泌尿、内分泌、骨科等)", + "2. **起病特征分析**: 结合症状出现的时间进程和症状严重程度,准确评估起病模式(急性/亚急性/慢性)", + "3. **初步诊断推断**: 运用临床医学知识,按照可能性大小排序,提出2-4个最可能的诊断假设", + "4. **评估重点制定**: 针对推断的疾病类型,为关键子任务确定具体的评估重点和收集方向", + "", + "## 重点子任务评估指导", + "- **诊疗经过**: 根据疾病特点,确定最关键的诊疗信息收集重点(如检查结果、治疗反应等)", + "- **主要症状特征**: 针对核心症状,确定需要深入探究的具体特征细节", + "- **伴随症状**: 基于疾病的病理生理特点,识别可能的相关症状表现", + "- **病情发展与演变**: 关注疾病的发展规律、诱发因素和缓解因素", + "", + "## 输出要求和质量标准", + "1. **格式要求**: 严格按照 DiseaseAnalysisResult 的 JSON 结构输出,不得省略任何必需字段", + "2. **内容质量**: 评估重点必须具体明确、具有可操作性,避免泛泛而谈的描述", + "3. **医学专业性**: 基于循证医学证据和临床最佳实践,考虑疾病的病理生理机制", + "4. **实用性**: 重视临床实用性,确保评估重点能够有效指导后续的专项病史收集工作", + "", + "## 示例输出格式(JSON)", + "{", + " \"disease_category\": \"神经系统疾病\",", + " \"suspected_conditions\": [\"偶发性头痛\", \"紧张性头痛\", \"丘脑下部功能异常\"],", + " \"onset_pattern\": \"亚急性\",", + " \"severity_level\": \"中度\",", + " \"evaluation_priorities\": {", + " \"诊疗经过\": [\"头部CT/MRI检查结果\", \"镇痛药物使用及效果\", \"神经内科就诊情况\"],", + " \"主要症状特征\": [\"头痛的具体部位和性质\", \"头痛的发作频率和持续时间\", \"头痛的严重程度评估\"],", + " \"伴随症状\": [\"是否伴有恶心呕吐\", \"是否有视物模糊或复视\", \"是否存在睡眠障碍\"],", + " \"病情发展与演变\": [\"头痛的诱发因素分析\", \"头痛的缓解方式和程度\", \"病情的发展趋势和周期性\"]", + " },", + " \"medical_reasoning\": \"患者主述为反复性头痛,结合起病特点和症状表现,首先考虑原发性头痛疾病。需进一步收集头痛的具体特征、诱发因素和伴随症状,同时关注既往检查和治疗情况,以明确诊断和制定下一步诊疗计划。\"", + "}" + ] + + @staticmethod + def get_example_output() -> str: + """ + 获取示例输出格式,用于指导 LLM 生成符合要求的结构化输出 + + Returns: + str: JSON 格式的示例输出 + """ + return """{ + "disease_category": "疾病类别(如神经系统疾病)", + "suspected_conditions": ["可能诊断1", "可能诊断2", "可能诊断3"], + "onset_pattern": "起病模式(急性/亚急性/慢性)", + "severity_level": "严重程度(轻度/中度/重度)", + "evaluation_priorities": { + "诊疗经过": ["重点信息1", "重点信息2", "重点信息3"], + "主要症状特征": ["重点特征1", "重点特征2", "重点特征3"], + "伴随症状": ["重点症状1", "重点症状2", "重点症状3"], + "病情发展与演变": ["重点发展1", "重点发展2", "重点发展3"] + }, + "medical_reasoning": "详细的医学分析推理过程,包括诊断依据和评估重点的制定理由" +}""" \ No newline at end of file diff --git a/agent_system/disease_analyzer/response_model.py b/agent_system/disease_analyzer/response_model.py new file mode 100644 index 0000000..4891220 --- /dev/null +++ b/agent_system/disease_analyzer/response_model.py @@ -0,0 +1,32 @@ +from typing import List, Dict, Any +from pydantic import Field +from agent_system.base import BaseResponseModel + +class DiseaseAnalysisResult(BaseResponseModel): + """ + 疾病上下文分析结果模型 + """ + disease_category: str = Field( + ..., + description="疾病类别(如:神经系统疾病、心血管疾病、呼吸系统疾病等)" + ) + suspected_conditions: List[str] = Field( + default_factory=list, + description="可能的疾病诊断列表" + ) + onset_pattern: str = Field( + ..., + description="起病模式(急性、亚急性、慢性)" + ) + severity_level: str = Field( + ..., + description="疾病严重程度(轻度、中度、重度)" + ) + evaluation_priorities: Dict[str, List[str]] = Field( + default_factory=dict, + description="各子任务的评估重点,key为子任务名称,value为重点因素列表" + ) + medical_reasoning: str = Field( + ..., + description="医学分析推理过程" + ) \ No newline at end of file diff --git a/config.py b/config.py new file mode 100644 index 0000000..3aafbb4 --- /dev/null +++ b/config.py @@ -0,0 +1,88 @@ +import os + +API_KEY = "sk-263038d4bf4e46a0bed16532587cff40" + +# {project_root}/medsynthai +BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + +# LLM model configuration based on agno +LLM_CONFIG = { + "deepseek": { + "class": "DeepSeek", + "params": { + "id": "deepseek-chat", + "api_key": API_KEY, + "base_url": "https://api.deepseek.com" + } + }, + "ollama": { + "class": "Ollama", + "params": { + "id": "qwen2.5:latest", + "host": "127.0.0.1" + } + }, + "deepseek-v3": { + "class": "OpenAILike", + "params": { + "id": "deepseek-v3", + "base_url": "https://dashscope.aliyuncs.com/compatible-mode/v1", + "api_key": API_KEY + } + }, + "deepseek-r1": { + "class": "OpenAILike", + "params": { + "id": "deepseek-r1", + "base_url": "https://dashscope.aliyuncs.com/compatible-mode/v1", + "api_key": API_KEY + } + }, + "qwen-max": { + "class": "OpenAILike", + "params": { + "id": "qwen-max", + "base_url": "https://dashscope.aliyuncs.com/compatible-mode/v1", + "api_key": API_KEY + } + }, + "qwen-vl-max": { + "class": "OpenAILike", # 使用OpenAI兼容类 + "params": { + "id": "qwen-vl-max", + "base_url": "https://dashscope.aliyuncs.com/compatible-mode/v1", # OpenAI兼容端点 # 降低随机性,提高结果一致性 + "api_key": API_KEY + } + }, + "aliyun": { + "class": "OpenAILike", + "params": { + "id": "qwen-max", # 默认使用qwen-max模型 + "base_url": "https://dashscope.aliyuncs.com/compatible-mode/v1", + "api_key": API_KEY + } + } + +} + +AGENT_CONFIG = { + "medical_image_analysis_agent": "qwen-vl-max" +} + +RAG_CONFIG = { + "lightrag": { + "working_dir": "./Vector_DB_Med", + "tokenizer_name": "trueto/medbert-base-chinese", + "model_name": "trueto/medbert-base-chinese", + "embedding_dim": 768, + "max_token_size": 512 + }, + "chroma_db": { + "api_key": API_KEY, + "base_url": "https://dashscope.aliyuncs.com/compatible-mode/v1", + "collection_name": "doctor", + "batch_size": 100, + "chroma_db_path": os.path.join(BASE_DIR, "static/rag/chroma_db"), + "csv_path": os.path.join(BASE_DIR, "static/files/zhongkang_doctor_list.csv") + } +} diff --git a/pyproject.toml b/pyproject.toml index ef8a065..021024b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,5 +8,7 @@ dependencies = [ "agno>=1.7.9", "ollama>=0.5.3", "openai>=1.99.6", + "packaging>=25.0", "pydantic>=2.11.7", + "sqlalchemy>=2.0.42", ] diff --git a/uv.lock b/uv.lock index 86013ae..48d1134 100644 --- a/uv.lock +++ b/uv.lock @@ -33,7 +33,9 @@ dependencies = [ { name = "agno" }, { name = "ollama" }, { name = "openai" }, + { name = "packaging" }, { name = "pydantic" }, + { name = "sqlalchemy" }, ] [package.metadata] @@ -41,7 +43,9 @@ requires-dist = [ { name = "agno", specifier = ">=1.7.9" }, { name = "ollama", specifier = ">=0.5.3" }, { name = "openai", specifier = ">=1.99.6" }, + { name = "packaging", specifier = ">=25.0" }, { name = "pydantic", specifier = ">=2.11.7" }, + { name = "sqlalchemy", specifier = ">=2.0.42" }, ] [[package]] @@ -138,6 +142,30 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/01/61/d4b89fec821f72385526e1b9d9a3a0385dda4a72b206d28049e2c7cd39b8/gitpython-3.1.45-py3-none-any.whl", hash = "sha256:8908cb2e02fb3b93b7eb0f2827125cb699869470432cc885f019b8fd0fccff77", size = 208168, upload-time = "2025-07-24T03:45:52.517Z" }, ] +[[package]] +name = "greenlet" +version = "3.2.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/03/b8/704d753a5a45507a7aab61f18db9509302ed3d0a27ac7e0359ec2905b1a6/greenlet-3.2.4.tar.gz", hash = "sha256:0dca0d95ff849f9a364385f36ab49f50065d76964944638be9691e1832e9f86d", size = 188260, upload-time = "2025-08-07T13:24:33.51Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/49/e8/58c7f85958bda41dafea50497cbd59738c5c43dbbea5ee83d651234398f4/greenlet-3.2.4-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:1a921e542453fe531144e91e1feedf12e07351b1cf6c9e8a3325ea600a715a31", size = 272814, upload-time = "2025-08-07T13:15:50.011Z" }, + { url = "https://files.pythonhosted.org/packages/62/dd/b9f59862e9e257a16e4e610480cfffd29e3fae018a68c2332090b53aac3d/greenlet-3.2.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:cd3c8e693bff0fff6ba55f140bf390fa92c994083f838fece0f63be121334945", size = 641073, upload-time = "2025-08-07T13:42:57.23Z" }, + { url = "https://files.pythonhosted.org/packages/f7/0b/bc13f787394920b23073ca3b6c4a7a21396301ed75a655bcb47196b50e6e/greenlet-3.2.4-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:710638eb93b1fa52823aa91bf75326f9ecdfd5e0466f00789246a5280f4ba0fc", size = 655191, upload-time = "2025-08-07T13:45:29.752Z" }, + { url = "https://files.pythonhosted.org/packages/f2/d6/6adde57d1345a8d0f14d31e4ab9c23cfe8e2cd39c3baf7674b4b0338d266/greenlet-3.2.4-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:c5111ccdc9c88f423426df3fd1811bfc40ed66264d35aa373420a34377efc98a", size = 649516, upload-time = "2025-08-07T13:53:16.314Z" }, + { url = "https://files.pythonhosted.org/packages/7f/3b/3a3328a788d4a473889a2d403199932be55b1b0060f4ddd96ee7cdfcad10/greenlet-3.2.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d76383238584e9711e20ebe14db6c88ddcedc1829a9ad31a584389463b5aa504", size = 652169, upload-time = "2025-08-07T13:18:32.861Z" }, + { url = "https://files.pythonhosted.org/packages/ee/43/3cecdc0349359e1a527cbf2e3e28e5f8f06d3343aaf82ca13437a9aa290f/greenlet-3.2.4-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:23768528f2911bcd7e475210822ffb5254ed10d71f4028387e5a99b4c6699671", size = 610497, upload-time = "2025-08-07T13:18:31.636Z" }, + { url = "https://files.pythonhosted.org/packages/b8/19/06b6cf5d604e2c382a6f31cafafd6f33d5dea706f4db7bdab184bad2b21d/greenlet-3.2.4-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:00fadb3fedccc447f517ee0d3fd8fe49eae949e1cd0f6a611818f4f6fb7dc83b", size = 1121662, upload-time = "2025-08-07T13:42:41.117Z" }, + { url = "https://files.pythonhosted.org/packages/a2/15/0d5e4e1a66fab130d98168fe984c509249c833c1a3c16806b90f253ce7b9/greenlet-3.2.4-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:d25c5091190f2dc0eaa3f950252122edbbadbb682aa7b1ef2f8af0f8c0afefae", size = 1149210, upload-time = "2025-08-07T13:18:24.072Z" }, + { url = "https://files.pythonhosted.org/packages/0b/55/2321e43595e6801e105fcfdee02b34c0f996eb71e6ddffca6b10b7e1d771/greenlet-3.2.4-cp313-cp313-win_amd64.whl", hash = "sha256:554b03b6e73aaabec3745364d6239e9e012d64c68ccd0b8430c64ccc14939a8b", size = 299685, upload-time = "2025-08-07T13:24:38.824Z" }, + { url = "https://files.pythonhosted.org/packages/22/5c/85273fd7cc388285632b0498dbbab97596e04b154933dfe0f3e68156c68c/greenlet-3.2.4-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:49a30d5fda2507ae77be16479bdb62a660fa51b1eb4928b524975b3bde77b3c0", size = 273586, upload-time = "2025-08-07T13:16:08.004Z" }, + { url = "https://files.pythonhosted.org/packages/d1/75/10aeeaa3da9332c2e761e4c50d4c3556c21113ee3f0afa2cf5769946f7a3/greenlet-3.2.4-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:299fd615cd8fc86267b47597123e3f43ad79c9d8a22bebdce535e53550763e2f", size = 686346, upload-time = "2025-08-07T13:42:59.944Z" }, + { url = "https://files.pythonhosted.org/packages/c0/aa/687d6b12ffb505a4447567d1f3abea23bd20e73a5bed63871178e0831b7a/greenlet-3.2.4-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:c17b6b34111ea72fc5a4e4beec9711d2226285f0386ea83477cbb97c30a3f3a5", size = 699218, upload-time = "2025-08-07T13:45:30.969Z" }, + { url = "https://files.pythonhosted.org/packages/dc/8b/29aae55436521f1d6f8ff4e12fb676f3400de7fcf27fccd1d4d17fd8fecd/greenlet-3.2.4-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:b4a1870c51720687af7fa3e7cda6d08d801dae660f75a76f3845b642b4da6ee1", size = 694659, upload-time = "2025-08-07T13:53:17.759Z" }, + { url = "https://files.pythonhosted.org/packages/92/2e/ea25914b1ebfde93b6fc4ff46d6864564fba59024e928bdc7de475affc25/greenlet-3.2.4-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:061dc4cf2c34852b052a8620d40f36324554bc192be474b9e9770e8c042fd735", size = 695355, upload-time = "2025-08-07T13:18:34.517Z" }, + { url = "https://files.pythonhosted.org/packages/72/60/fc56c62046ec17f6b0d3060564562c64c862948c9d4bc8aa807cf5bd74f4/greenlet-3.2.4-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:44358b9bf66c8576a9f57a590d5f5d6e72fa4228b763d0e43fee6d3b06d3a337", size = 657512, upload-time = "2025-08-07T13:18:33.969Z" }, + { url = "https://files.pythonhosted.org/packages/e3/a5/6ddab2b4c112be95601c13428db1d8b6608a8b6039816f2ba09c346c08fc/greenlet-3.2.4-cp314-cp314-win_amd64.whl", hash = "sha256:e37ab26028f12dbb0ff65f29a8d3d44a765c61e729647bf2ddfbbed621726f01", size = 303425, upload-time = "2025-08-07T13:32:27.59Z" }, +] + [[package]] name = "h11" version = "0.16.0" @@ -273,6 +301,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d6/dd/9aa956485c2856346b3181542fbb0aea4e5b457fa7a523944726746da8da/openai-1.99.6-py3-none-any.whl", hash = "sha256:e40d44b2989588c45ce13819598788b77b8fb80ba2f7ae95ce90d14e46f1bd26", size = 786296, upload-time = "2025-08-09T15:20:51.95Z" }, ] +[[package]] +name = "packaging" +version = "25.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a1/d4/1fc4078c65507b51b96ca8f8c3ba19e6a61c8253c72794544580a7b6c24d/packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f", size = 165727, upload-time = "2025-04-19T11:48:59.673Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469, upload-time = "2025-04-19T11:48:57.875Z" }, +] + [[package]] name = "pydantic" version = "2.11.7" @@ -414,6 +451,27 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235, upload-time = "2024-02-25T23:20:01.196Z" }, ] +[[package]] +name = "sqlalchemy" +version = "2.0.42" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "greenlet", marker = "(python_full_version < '3.14' and platform_machine == 'AMD64') or (python_full_version < '3.14' and platform_machine == 'WIN32') or (python_full_version < '3.14' and platform_machine == 'aarch64') or (python_full_version < '3.14' and platform_machine == 'amd64') or (python_full_version < '3.14' and platform_machine == 'ppc64le') or (python_full_version < '3.14' and platform_machine == 'win32') or (python_full_version < '3.14' and platform_machine == 'x86_64')" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5a/03/a0af991e3a43174d6b83fca4fb399745abceddd1171bdabae48ce877ff47/sqlalchemy-2.0.42.tar.gz", hash = "sha256:160bedd8a5c28765bd5be4dec2d881e109e33b34922e50a3b881a7681773ac5f", size = 9749972, upload-time = "2025-07-29T12:48:09.323Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e9/7e/25d8c28b86730c9fb0e09156f601d7a96d1c634043bf8ba36513eb78887b/sqlalchemy-2.0.42-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:941804f55c7d507334da38133268e3f6e5b0340d584ba0f277dd884197f4ae8c", size = 2127905, upload-time = "2025-07-29T13:29:22.249Z" }, + { url = "https://files.pythonhosted.org/packages/e5/a1/9d8c93434d1d983880d976400fcb7895a79576bd94dca61c3b7b90b1ed0d/sqlalchemy-2.0.42-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:95d3d06a968a760ce2aa6a5889fefcbdd53ca935735e0768e1db046ec08cbf01", size = 2115726, upload-time = "2025-07-29T13:29:23.496Z" }, + { url = "https://files.pythonhosted.org/packages/a2/cc/d33646fcc24c87cc4e30a03556b611a4e7bcfa69a4c935bffb923e3c89f4/sqlalchemy-2.0.42-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4cf10396a8a700a0f38ccd220d940be529c8f64435c5d5b29375acab9267a6c9", size = 3246007, upload-time = "2025-07-29T13:26:44.166Z" }, + { url = "https://files.pythonhosted.org/packages/67/08/4e6c533d4c7f5e7c4cbb6fe8a2c4e813202a40f05700d4009a44ec6e236d/sqlalchemy-2.0.42-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9cae6c2b05326d7c2c7c0519f323f90e0fb9e8afa783c6a05bb9ee92a90d0f04", size = 3250919, upload-time = "2025-07-29T13:22:33.74Z" }, + { url = "https://files.pythonhosted.org/packages/5c/82/f680e9a636d217aece1b9a8030d18ad2b59b5e216e0c94e03ad86b344af3/sqlalchemy-2.0.42-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f50f7b20677b23cfb35b6afcd8372b2feb348a38e3033f6447ee0704540be894", size = 3180546, upload-time = "2025-07-29T13:26:45.648Z" }, + { url = "https://files.pythonhosted.org/packages/7d/a2/8c8f6325f153894afa3775584c429cc936353fb1db26eddb60a549d0ff4b/sqlalchemy-2.0.42-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9d88a1c0d66d24e229e3938e1ef16ebdbd2bf4ced93af6eff55225f7465cf350", size = 3216683, upload-time = "2025-07-29T13:22:34.977Z" }, + { url = "https://files.pythonhosted.org/packages/39/44/3a451d7fa4482a8ffdf364e803ddc2cfcafc1c4635fb366f169ecc2c3b11/sqlalchemy-2.0.42-cp313-cp313-win32.whl", hash = "sha256:45c842c94c9ad546c72225a0c0d1ae8ef3f7c212484be3d429715a062970e87f", size = 2093990, upload-time = "2025-07-29T13:16:13.036Z" }, + { url = "https://files.pythonhosted.org/packages/4b/9e/9bce34f67aea0251c8ac104f7bdb2229d58fb2e86a4ad8807999c4bee34b/sqlalchemy-2.0.42-cp313-cp313-win_amd64.whl", hash = "sha256:eb9905f7f1e49fd57a7ed6269bc567fcbbdac9feadff20ad6bd7707266a91577", size = 2120473, upload-time = "2025-07-29T13:16:14.502Z" }, + { url = "https://files.pythonhosted.org/packages/ee/55/ba2546ab09a6adebc521bf3974440dc1d8c06ed342cceb30ed62a8858835/sqlalchemy-2.0.42-py3-none-any.whl", hash = "sha256:defcdff7e661f0043daa381832af65d616e060ddb54d3fe4476f51df7eaa1835", size = 1922072, upload-time = "2025-07-29T13:09:17.061Z" }, +] + [[package]] name = "tomli" version = "2.2.1"