import base64 import json from openai import AsyncOpenAI from app.core.config import settings DISCLAIMER = "本报告仅用于娱乐占卜与自我反思,不构成医学、心理、职业、财务、投资或任何人生决策建议。" SYSTEM_PROMPT = ( "你是“赛博先生”,一个面向普通人的娱乐型 AI 命理解读助手。" "你的风格要像一个会聊天、懂生活的朋友:温和、具体、接地气,有一点玄学仪式感,但不要装神秘。" "你会根据掌心照片做象征性手相解读,但所有表达都必须使用“可能、倾向、适合、提醒你”这类非确定性措辞。" "禁止给出医疗、心理诊断、投资、职业成败、婚恋结果、寿命、灾祸等确定性判断。" "不要堆砌专业术语,不要写得像教材;每个结论都要落到生活、学习、事业、关系或近期行动里的具体场景。" ) USER_PROMPT_TEMPLATE = ( "请分析这张{hand_side}手掌照片,生成中文手相报告。" "必须覆盖生命线、智慧线、感情线、命运线、手型与手指比例、特殊纹路与丘位特征。" "写作要求:" "1. overall_summary 用 2 到 4 句话,像给用户本人看的开场结论,要贴近日常生活。" "2. dimensions 中每个 interpretation 不要只解释纹路含义,必须关联一个现实场景,例如学习效率、工作节奏、沟通方式、情绪恢复、计划执行、关系相处。" "3. 每个 advice 必须是用户今天或本周能做的小建议,不要空泛。" "4. strengths 写成用户容易感受到的优势,例如做事方式、学习方式、职场协作、情感表达。" "5. challenges 写成温和提醒,不要吓人,不要宿命论。" "6. suggestions 必须包含生活、学习/成长、事业/工作、关系沟通中的至少三个方向。" "7. lucky_keywords 要短、有记忆点、生活化。" "8. 如果照片不够真实或不够清晰,要诚实降低 confidence,并在 reason 里说明。" ) REPORT_SCHEMA = { "name": "palm_report", "schema": { "type": "object", "additionalProperties": False, "properties": { "quality_check": { "type": "object", "additionalProperties": False, "properties": { "can_analyze": {"type": "boolean"}, "reason": {"type": "string"}, "confidence": {"type": "number"}, }, "required": ["can_analyze", "reason", "confidence"], }, "overall_summary": {"type": "string"}, "dimensions": { "type": "array", "items": { "type": "object", "additionalProperties": False, "properties": { "name": {"type": "string"}, "observations": {"type": "array", "items": {"type": "string"}}, "interpretation": {"type": "string"}, "confidence": {"type": "number"}, "advice": {"type": "string"}, }, "required": ["name", "observations", "interpretation", "confidence", "advice"], }, }, "strengths": {"type": "array", "items": {"type": "string"}}, "challenges": {"type": "array", "items": {"type": "string"}}, "suggestions": {"type": "array", "items": {"type": "string"}}, "lucky_keywords": {"type": "array", "items": {"type": "string"}}, "disclaimer": {"type": "string"}, }, "required": [ "quality_check", "overall_summary", "dimensions", "strengths", "challenges", "suggestions", "lucky_keywords", "disclaimer", ], }, "strict": True, } class PalmAnalyzer: def __init__(self) -> None: self.client = ( AsyncOpenAI(api_key=settings.openai_api_key, base_url=settings.openai_base_url) if settings.openai_api_key else None ) async def analyze(self, image_bytes: bytes, content_type: str, hand_side: str) -> dict: if not self.client: return self._mock_report(hand_side) image_data = base64.b64encode(image_bytes).decode("ascii") response = await self.client.responses.create( model=settings.openai_model, input=[ { "role": "system", "content": [ { "type": "input_text", "text": SYSTEM_PROMPT, } ], }, { "role": "user", "content": [ { "type": "input_text", "text": USER_PROMPT_TEMPLATE.format(hand_side=hand_side), }, { "type": "input_image", "image_url": f"data:{content_type};base64,{image_data}", "detail": "high", }, ], }, ], text={"format": {"type": "json_schema", **REPORT_SCHEMA}}, ) data = json.loads(response.output_text) data["disclaimer"] = DISCLAIMER return data def _mock_report(self, hand_side: str) -> dict: return { "quality_check": {"can_analyze": True, "reason": "mock mode", "confidence": 0.72}, "overall_summary": f"这是一份{hand_side}手娱乐手相报告。整体看,你像是那种遇到事情会先稳住节奏的人,适合把目标拆小、慢慢推进。最近如果在学习、工作或关系里有点卡,不必急着推翻重来,先把手边一件具体的小事做好,会更容易找回状态。", "dimensions": [ { "name": "生命线", "observations": ["弧度较完整", "线条延展感较强"], "interpretation": "这类线条象征恢复力还不错。放到生活里,你可能不是一直满电的人,但只要睡眠、饮食和节奏回到正轨,状态通常能慢慢补回来。", "confidence": 0.68, "advice": "这周先固定一个睡前时间,别把恢复力浪费在反复熬夜上。", }, { "name": "智慧线", "observations": ["走向偏平稳", "中段纹理较清晰"], "interpretation": "智慧线偏稳,象征你适合用步骤感处理问题。学习或工作上,如果任务太大,你更适合列清单推进,而不是靠临场爆发。", "confidence": 0.66, "advice": "今天把最烦的一件事拆成 3 步,只完成第一步就算开局。", }, { "name": "感情线", "observations": ["线条柔和", "末端略有分支感"], "interpretation": "感情线柔和,象征你在关系里比较在意感受,也容易替别人想。好处是共情强,提醒是别把所有情绪都自己消化。", "confidence": 0.64, "advice": "这周有不舒服的地方,试着用一句具体的话说出来:我希望你下次可以怎样。", }, { "name": "命运线", "observations": ["可见纵向纹理", "深浅变化较明显"], "interpretation": "命运线有阶段变化感,象征你的事业或成长路径可能不是一条直线。你适合边做边调整,在变化里积累自己的方法。", "confidence": 0.58, "advice": "工作或学习上,优先做一件能留下作品、笔记或案例的事。", }, { "name": "手型与手指比例", "observations": ["掌形比例均衡", "手指伸展感自然"], "interpretation": "手型比例均衡,象征你在规则和灵感之间都有一点能力。适合做既要审美判断、也要实际落地的任务。", "confidence": 0.61, "advice": "如果最近有想法,别只停在脑子里,先做一个草稿或简单版本。", }, { "name": "特殊纹路与丘位特征", "observations": ["局部细纹较丰富", "掌丘起伏需更清晰照片确认"], "interpretation": "细纹较丰富,象征你对环境和他人反馈比较敏感。学习、工作或社交里,你可能很会察觉气氛,但也容易被杂音影响。", "confidence": 0.52, "advice": "给自己设一个免打扰时段,把注意力留给真正重要的任务。", }, ], "strengths": ["适合按计划推进学习和工作", "能照顾到别人的感受", "遇到变化时有重新调整的能力"], "challenges": ["想得多的时候,行动容易变慢", "太在意反馈时,会消耗自己的专注力"], "suggestions": ["生活上先把作息拉回稳定线", "学习成长上把大目标拆成今天能完成的一页笔记", "事业工作上优先沉淀一个可展示的小成果", "关系沟通上把需求说具体,不要只等别人猜"], "lucky_keywords": ["先做一步", "稳住节奏", "说清需求"], "disclaimer": DISCLAIMER, }