import gradio as gr import requests import json import os # === Gemini API 設定(比照你另一個機器人) === GEMINI_API_KEY = os.getenv("GEMINI_API_KEY") API_URL = f"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key={GEMINI_API_KEY}" SYSTEM_PROMPT = """ 【成分人體效應模擬要求】 請依據下列科學生理機制,模擬「每一個成分」進入人體後在各系統的可能作用。模型必須基於以下框架逐步推演,而非捏造研究結果: 1. 吸收(Absorption) - 以成分的化學性質(極性、溶解性、粒徑、離子化狀態)推估腸胃道吸收率與速率 - 若為礦物、金屬或無機物質,要明確評估其溶解、解離與吸收途徑 - 若資料不足,請標示為「資料有限,以下為推測性機轉」 2. 分布(Distribution) - 模擬成分在血液、淋巴系統、肝臟、腎臟、肌肉、脂肪或細胞外液的分布情形 - 依分子大小/帶電情形推估是否能進入細胞、穿越血腦障壁、或累積於肝腎 - 若成分能調整腸道菌相,其效應以「微生物代謝物與宿主免疫反應」方式表達 3. 代謝(Metabolism) - 成分是否需要肝臟 Phase I/Phase II 代謝? - 是否可能抑制/誘導 CYP450(如 CYP3A4、2C19、1A2 等) - 是否會影響氧化還原反應、自由基清除、炎症訊號? 4. 排泄(Excretion) - 評估腎臟、膽汁、糞便途徑 - 無機成分若不被代謝,需評估體內累積或沉積的可能性。 5. 細胞與分子層級作用(Mechanistic Simulation) 請基於: - 酸鹼變化 - 離子交換 - 膜電位影響 - 免疫調節(先天/後天免疫) - 氧化還原反應(ROS / RNS) - 受體參與或酵素抑制/活化(若已知) - 微生物代謝副產物與宿主交互作用 並模擬可能的: - 生理效應(如血糖、血壓、腸胃道 Motility) - 細胞層效應(如 Ca2+ 流動、ROS 下降或上升) - 免疫系統效應(如促炎/抗炎傾向) - 內分泌影響 - 神經系統反應(如交感/副交感調節) 6. 成分之間的相互作用(Interaction Simulation) 請評估: - 化學層面(酸鹼反應、螯合、沉澱、氧化還原) - 生物層面(共同影響肝臟酵素、腎臟負擔、中樞神經、腸道菌相) - 功效層面(加乘、拮抗、不相容) 若屬推測性,請使用「推測性機轉」標記。 7. 與用途的匹配度(Mechanism-Utility Match) - 判斷此配方內的機轉是否真正有助於使用者輸入的用途 - 若用途與機轉不符,需清楚指出 - 對整體配方給出「低/中/高」風險與科學合理性評估 【重要限制】 - 不得捏造臨床試驗數據 - 不得提供劑量建議 - 所有未知處以「資料有限」標記 """ INTRO_MD = """ # 成分安全性與交互作用評估beta 輸入主成分、其餘成分、產品類型與預期用途,系統會產生一份簡易的安全性與交互作用報告。 > 本工具僅提供一般性科學與安全性資訊整理,**不構成醫療診斷或處方建議**。 """ def build_prompt(main_ingredient: str, other_ingredients: str, product_type: str, purpose: str) -> str: user_block = f""" 主成分:{main_ingredient} 其餘成分: {other_ingredients} 產品類型:{product_type} 預期用途:{purpose} 請依照系統提示詞的規範,產生一份結構化的中文報告。 """ return SYSTEM_PROMPT.strip() + "\n\n==== 使用者輸入 ====\n" + user_block.strip() def call_gemini_api(prompt: str) -> str: if not GEMINI_API_KEY: return "【設定錯誤】找不到 GEMINI_API_KEY,請在 Hugging Face Space 的 Secrets 中設定。" headers = {"Content-Type": "application/json"} data = { "contents": [ { "parts": [ {"text": prompt} ] } ] } try: resp = requests.post(API_URL, headers=headers, data=json.dumps(data), timeout=60) except Exception as e: return f"【網路或連線錯誤】{e}" if resp.status_code != 200: return f"【API 錯誤 {resp.status_code}】{resp.text[:500]}" try: j = resp.json() text = j["candidates"][0]["content"]["parts"][0]["text"] return text.strip() except Exception as e: return f"【解析回應失敗】{e}|原始:{resp.text[:500]}" def analyze_formula(main_ingredient, other_ingredients, product_type, purpose): if not main_ingredient and not other_ingredients: return "請至少輸入主成分或其餘成分。" prompt = build_prompt(main_ingredient, other_ingredients, product_type, purpose) return call_gemini_api(prompt) def clear_all(): # 對應 outputs 的順序:主成分、其餘成分、產品類型、用途、報告 return "", "", "保健品", "", "(已清空)" with gr.Blocks(title="成分安全性與交互作用評估") as demo: gr.Markdown(INTRO_MD) with gr.Row(): main_ingredient = gr.Textbox( label="主成分", placeholder="例如:富氫碳酸鈣、維生素D3……" ) product_type = gr.Radio( label="產品類型", choices=["食品", "保健品", "藥品"], value="保健品", ) other_ingredients = gr.Textbox( label="其餘成分", lines=4, placeholder="用逗號或換行分隔,例如:麥芽糊精、硬脂酸鎂、明膠膠囊……" ) purpose = gr.Textbox( label="預期用途", lines=3, placeholder="例如:協助入睡、運動後恢復、長期糖尿病患者補充鈣質……" ) report = gr.Markdown(label="分析報告") with gr.Row(): analyze_btn = gr.Button("分析配方", variant="primary") clear_btn = gr.Button("清空", variant="secondary") analyze_btn.click( fn=analyze_formula, inputs=[main_ingredient, other_ingredients, product_type, purpose], outputs=report, ) clear_btn.click( fn=clear_all, inputs=[], outputs=[main_ingredient, other_ingredients, product_type, purpose, report], ) if __name__ == "__main__": demo.launch()