fzd4 / app.py
fdbw's picture
Update app.py
028a160 verified
Raw
History Blame Contribute Delete
6.48 kB
import os
import base64
import gradio as gr
from openai import OpenAI
def encode_image(image_path):
"""将本地图片文件转换为 Base64 编码"""
with open(image_path, "rb") as image_file:
return base64.b64encode(image_file.read()).decode('utf-8')
def detect_language(text, history):
"""
智能检测用户语言:
1. 优先从当前提问检测
2. 若当前无文字,从最近一轮用户历史中推断
3. 默认返回中文
"""
# 1. 检查当前提问
if text:
clean_text = str(text).strip()
if clean_text:
# 计算中文字符和英文字母比例
chinese_chars = sum(1 for char in clean_text if '\u4e00' <= char <= '\u9fff')
alpha_chars = sum(1 for char in clean_text if char.isalpha())
if alpha_chars > 0:
# 中文字符占比 > 30% 判定为中文
if chinese_chars / alpha_chars > 0.3:
return "zh"
else:
return "en"
else:
# 没有字母(纯数字/符号),默认中文
return "zh"
# 2. 当前无文字,从历史中推断
for msg in reversed(history[-6:]):
if msg.get("role") == "user":
content = msg.get("content", "")
if isinstance(content, dict):
content = content.get("text", "")
if content:
clean_content = str(content).strip()
chinese_chars = sum(1 for char in clean_content if '\u4e00' <= char <= '\u9fff')
alpha_chars = sum(1 for char in clean_content if char.isalpha())
if alpha_chars > 0 and chinese_chars / alpha_chars > 0.3:
return "zh"
elif alpha_chars > 0:
return "en"
# 3. 默认中文
return "zh"
def predict(message, history):
api_key = os.getenv("SILICONFLOW_API_KEY", "")
if not api_key:
yield "❌ 未检测到 API Key!请先在 Space Settings -> Secrets 中添加 SILICONFLOW_API_KEY!"
return
api_key = api_key.strip()
try:
client = OpenAI(
api_key=api_key,
base_url="https://api.siliconflow.cn/v1"
)
text_content = ""
files = []
# Gradio 多模态输入解析
if isinstance(message, dict):
text_content = message.get("text", "")
files = message.get("files", [])
else:
text_content = str(message)
# 智能检测语言(含历史记忆)
user_lang = detect_language(text_content, history)
# 🔥 调试输出(可删除)
print(f"检测到语言: {user_lang}, 用户输入: {text_content[:50]}")
# 构建当前请求的 Message Payload
current_content = []
# 1. 解析当前上传的图片
for f in files:
file_path = f.get("path") if isinstance(f, dict) else f
if file_path:
try:
base64_img = encode_image(file_path)
current_content.append({
"type": "image_url",
"image_url": {"url": f"data:image/jpeg;base64,{base64_img}"}
})
except Exception as img_err:
print(f"图片读取失败: {img_err}")
# 2. 解析文本说明
if not text_content or not str(text_content).strip():
if user_lang == "en":
prompt_text = "Please observe this image carefully and tell me what plant this is and its key features."
else:
prompt_text = "请仔细观察这张图片,告诉我这是什么植物?有哪些特征?"
else:
prompt_text = str(text_content).strip()
current_content.append({"type": "text", "text": prompt_text})
# 3. 根据用户语言设置 System Prompt
if user_lang == "en":
system_prompt = (
"You are a professional botanist and nature expert. "
"Identify the plant in the image and provide its scientific name, "
"family, genus, and key features in **English**. "
"Be concise and accurate."
)
else:
system_prompt = (
"你是一位专业的植物学家和自然科普专家。"
"请精准识别图片中的植物,并用简洁明了的中文回答其名称、科属及特点。"
)
messages = [
{"role": "system", "content": system_prompt}
]
# 仅保留最近 2 轮纯文本历史
for msg in history[-4:]:
role = "user" if msg.get("role") == "user" else "assistant"
content_val = msg.get("content", "")
if isinstance(content_val, dict):
content_val = content_val.get("text", "")
if content_val and not str(content_val).startswith("data:image"):
messages.append({"role": role, "content": str(content_val)})
# 放入最新一轮包含图片的请求
messages.append({"role": "user", "content": current_content})
# 4. 调用视觉模型
response = client.chat.completions.create(
model="Qwen/Qwen3-VL-32B-Instruct",
messages=messages,
stream=True,
temperature=0.2
)
# 5. 流式输出
partial_text = ""
for chunk in response:
if chunk.choices and chunk.choices[0].delta.content:
partial_text += chunk.choices[0].delta.content
yield partial_text
except Exception as e:
err_msg = str(e)
if "30001" in err_msg or "insufficient" in err_msg.lower():
yield "⚠️ **请求失败:硅基流动账号余额不足**"
elif "30003" in err_msg or "Model disabled" in err_msg:
yield "⚠️ **模型不可用,请检查模型名称是否正确**"
else:
yield f"❌ 请求失败: {err_msg}"
# 创建 Gradio 界面
demo = gr.ChatInterface(
fn=predict,
title="🌱 AI 植物识别专家 (智能双语)",
description="🌍 智能识别你的提问语言:中文问→中文答,英文问→英文答。连续对话自动记忆语言偏好!",
multimodal=True
)
if __name__ == "__main__":
demo.launch(ssr_mode=False)