import gradio as gr import json import asyncio from pyodide.http import pyfetch # 浏览器内可用 ############################################################################### # 全局变量(与原来保持一致,方便 update_settings 直接修改) templates = { "default_v0.0.4_1K335": "# 糖度计AI Agent系统提示词\n\n## 核心功能\n你是一个专业的“糖度计”AI Agent,能够为输入的内容计算和评估“糖度”值。糖度有两种含义:\n1. **食物糖度**:使用Brix值衡量食物的实际含糖量\n2. **网络俚语糖度**:衡量事件、人物、行为等对周围环境产生的负面影响程度或令人感到羞愧/恶心/低能/离谱的程度\n\n## 输出格式要求\n**只输出一个浮点数表示糖度**\n\n## 数值评分标准\n\n### 食物类输入(Brix糖度)\n- **0.0-5.0**:几乎无糖(如纯水、某些蔬菜)\n- **5.0-15.0**:低糖(如西瓜、柠檬、大部分蔬菜)\n- **15.0-25.0**:中等糖度(如苹果、橙子、胡萝卜)\n- **25.0-40.0**:高糖(如葡萄、香蕉、甜瓜)\n- **40.0-70.0**:极高糖度(如蜂蜜、果酱、糖浆)\n- **70.0-100.0**:接近纯糖(如白砂糖、冰糖)\n\n### 事件/人物类输入(网络俚语糖度)\n- **0.0-10.0**:轻微尴尬或小负面影响\n- **10.0-30.0**:中等程度的令人不适或羞愧\n- **30.0-50.0**:较强的负面影响,令人反感,低能\n- **50.0-70.0**:严重的恶心感或强烈羞愧\n- **70.0-100.0**:极度令人厌恶,产生巨大负面影响\n- **100.0以上**:史诗级糖度,令人难以忘怀的极端负面事件,极度无能\n\n## 评分参考因素\n\n### 食物评分依据\n- 查阅真实的Brix值数据\n- 考虑食物的自然含糖量\n- 区分天然糖分和添加糖分\n- 参考科学测量标准\n\n### 事件/人物评分依据\n- **社会影响**:对公众或群体造成的负面影响范围和深度\n- **道德层面**:违背社会伦理道德的程度\n- **尴尬程度**:令当事人或观众感到羞愧的强度\n- **持续影响**:负面影响的持久性和传播性\n- **公众反应**:社会舆论的激烈程度和一致性\n\n## 特殊情况处理\n1. **信息不足**:根据常识给出合理估值(范围0.0-100.0)\n2. **歧义输入**:优先按照上下文判断是食物还是事件\n3. **争议性内容**:保持客观中立,基于公认事实评分\n4. **极端情况**:糖度过高时可超过100\n\n## 示例输出\n\n### 食物类\n输入:“蜂蜜”\n输出:`82.5`\n\n输入:“黄瓜”\n输出:`2.8`\n\n### 事件/人物类\n输入:“公共场所大声接电话”\n输出:`15.2`\n\n输入“网红直播带货虚假宣传被曝光”\n输出:`68.9`\n\n## 执行指令\n1. 仔细分析输入内容的类型和背景\n2. 根据相应标准进行评分\n3. **只输出浮点数值,不要任何解释或评价文字**\n4. 数值范围控制在【0.000000,100.000000】,极端情况可超过100\n5. 信息不足时给出合理估值,**不允许输出负值**\n\n**记住:始终保持客观公正,基于事实评分,只输出数值结果。**", "default_v0.0.3_extra_223": "你是“糖度计”AI,根据输入:\n- 若为食物名称,输出其Brix糖度,浮点数,精确到6位小数(如苹果:约10.000000-15.000000)。\n- 若为事件/任务/行为,根据知识评估其“唐”度(低能/离谱/令人恶心/尴尬程度),输出浮点数,范围【0.000000, 100.000000】,稍微随机一点,+-5%,严格符合事实,评价一般事物不要走极端。极少数超100表示极度离谱,精确到6位小数。\n仅输出浮点数,无其他内容。" } api_url = "https://api.openai.com/v1/chat/completions" api_key = "" model_name = "gpt-4o-mini" ############################################################################### # ------------- 唯一需要动的地方:把 requests 换成 pyfetch ----------------- async def query_model(food_name, template_name): """调用 AI 模型获取糖度值(浏览器内异步版)""" prompt = templates.get(template_name, templates["default_v0.0.4_1K335"]) headers = { "Authorization": f"Bearer {api_key}", "Content-Type": "application/json" } payload = { "model": model_name, "messages": [ {"role": "system", "content": prompt}, {"role": "user", "content": food_name} ] } try: resp = await pyfetch( api_url, method="POST", headers=headers, body=json.dumps(payload) ) if not resp.ok: return "0.0", f"HTTP {resp.status}", f"HTTP {resp.status}" data = await resp.json() raw_output = data["choices"][0]["message"]["content"].strip() val = float(raw_output) except Exception as e: return "0.0", f"错误: {e}", f"错误: {e}" # 分类评语(完全沿用原逻辑) if val < 20.0: remark = "🟦 低糖" elif val < 60.0: remark = "🟩 中糖" elif val < 80.0: remark = "🟧 高糖" elif val <= 100.0: remark = "🟥 糖王" else: remark = "🌌 糖到没边" return str(val), remark, raw_output # -------------------------------------------------------------------------- def add_template(new_name, new_content): """添加新模版并同步更新两个下拉列表(原逻辑不动)""" if new_name and new_content: templates[new_name] = new_content updated_keys = list(templates.keys()) return updated_keys, gr.Dropdown(choices=updated_keys, value=new_name), f"✅ 模版 **{new_name}** 已添加" current_keys = list(templates.keys()) return current_keys, gr.Dropdown(choices=current_keys, value=current_keys[0]), "❌ 添加失败:名称或内容不能为空" def update_settings(url, model, key): """更新 API 设置(原逻辑不动)""" global api_url, model_name, api_key if url: api_url = url if model: model_name = model if key: api_key = key return f"✅ 已更新设置\nAPI URL: {api_url}\n模型: {model_name}" with gr.Blocks(title="糖度计") as demo: gr.Markdown("# 🍬 糖度计") gr.Markdown("###### forked by [rain_x3](https://www.luogu.com.cn/user/964072)") with gr.Tabs(): with gr.Tab("检测"): food_input = gr.Textbox(label="输入食物名称") template_dropdown = gr.Dropdown( choices=list(templates.keys()), value="default_v0.0.4_1K335", label="模版选择" ) btn = gr.Button("开始检测") with gr.Row(): val_output = gr.Textbox(label="糖度值", lines=1, interactive=False) remark_output = gr.Textbox(label="鉴定", lines=1, interactive=False) # 注意:Gradio Lite 按钮点击事件需要写成异步 btn.click(query_model, inputs=[food_input, template_dropdown], outputs=[val_output, remark_output]) with gr.Tab("模版管理"): new_name = gr.Textbox(label="新模版名称") new_content = gr.Textbox(label="新模版提示词", lines=5) add_btn = gr.Button("添加模版") template_list = gr.Dropdown(choices=list(templates.keys()), label="现有模版") add_status = gr.Textbox(label="状态", interactive=False) add_btn.click(add_template, inputs=[new_name, new_content], outputs=[template_list, template_dropdown, add_status]) with gr.Tab("高级设置"): api_url_in = gr.Textbox(label="API URL", value=api_url) model_in = gr.Textbox(label="模型名称", value=model_name) api_key_in = gr.Textbox(label="API Key", type="password", value=api_key) update_btn = gr.Button("更新设置") update_status = gr.Textbox(label="状态", interactive=False) update_btn.click(update_settings, inputs=[api_url_in, model_in, api_key_in], outputs=update_status) demo.launch()