Formula-beta / app.py
wensjheng's picture
Update app.py
d1ce63f verified
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()