import base64 import json from openai import AsyncOpenAI from app.ai.base import VisionProvider, TextProvider, VisionResult, DateResult, LeafletResult from app.config import settings class OpenAIVisionProvider(VisionProvider): def __init__(self): self.client = AsyncOpenAI(api_key=settings.OPENAI_API_KEY) self.model = settings.OPENAI_MODEL async def recognize_medicine(self, image_bytes: bytes) -> VisionResult: base64_image = base64.b64encode(image_bytes).decode('utf-8') response = await self.client.chat.completions.create( model=self.model, messages=[ { "role": "user", "content": [ { "type": "text", "text": """请识别这张药品包装图片中的信息,返回JSON格式: { "generic_name": "通用名称", "brand_name": "商品名称", "manufacturer": "生产厂家", "specification": "规格" } 只提取图片中真实出现的内容,不要猜测。""" }, { "type": "image_url", "image_url": { "url": f"data:image/jpeg;base64,{base64_image}" } } ] } ], response_format={"type": "json_object"} ) result = json.loads(response.choices[0].message.content) return VisionResult(**result) async def recognize_dates(self, image_bytes: bytes) -> DateResult: base64_image = base64.b64encode(image_bytes).decode('utf-8') response = await self.client.chat.completions.create( model=self.model, messages=[ { "role": "user", "content": [ { "type": "text", "text": """请识别这张图片中的日期信息,返回JSON格式: { "production_date": "生产日期(YYYY-MM-DD格式,如果无法识别则为null)", "expiry_date": "有效期/过期日期(YYYY-MM-DD格式,如果无法识别则为null)" } 只提取图片中真实出现的日期,不要猜测或推理。""" }, { "type": "image_url", "image_url": { "url": f"data:image/jpeg;base64,{base64_image}" } } ] } ], response_format={"type": "json_object"} ) result = json.loads(response.choices[0].message.content) return DateResult(**result) class OpenAITextProvider(TextProvider): def __init__(self): self.client = AsyncOpenAI(api_key=settings.OPENAI_API_KEY) self.model = "gpt-4" async def summarize_leaflet(self, text: str) -> LeafletResult: response = await self.client.chat.completions.create( model=self.model, messages=[ { "role": "system", "content": "你是一个医疗信息提取助手。请从药品说明书中提取关键信息。" }, { "role": "user", "content": f"""请从以下药品说明书中提取关键信息,返回JSON格式: {{ "indications": "适应症", "adult_dose": "成人用法用量", "child_dose": "儿童用法用量(如果没有则为null)", "contraindications": "禁忌", "notes": "注意事项(如果有)" }} 说明书内容: {text}""" } ], response_format={"type": "json_object"} ) result = json.loads(response.choices[0].message.content) return LeafletResult(**result) async def natural_language_search(self, query: str, medicines: list) -> list: medicines_text = "\n".join([ f"- {m['name']}: {m.get('indications', '')}" for m in medicines ]) response = await self.client.chat.completions.create( model=self.model, messages=[ { "role": "system", "content": "你是一个药品搜索助手。根据用户描述的症状,从药品列表中找出可能适用的药品。" }, { "role": "user", "content": f"""用户描述:{query} 可用药品列表: {medicines_text} 请返回JSON格式的搜索结果: {{ "results": [ {{ "medicine_id": 药品ID, "name": "药品名称", "reason": "匹配原因" }} ] }}""" } ], response_format={"type": "json_object"} ) result = json.loads(response.choices[0].message.content) return result.get('results', [])