File size: 3,703 Bytes
6f0bc13 e78e83f d7b63b0 49cbd08 6f0bc13 e78e83f 49cbd08 6f0bc13 49cbd08 6f0bc13 49cbd08 6f0bc13 d7b63b0 6f0bc13 d7b63b0 e78e83f 6f0bc13 49cbd08 6f0bc13 d7b63b0 6f0bc13 49cbd08 6f0bc13 d7b63b0 6f0bc13 49cbd08 6f0bc13 49cbd08 6f0bc13 49cbd08 6f0bc13 49cbd08 6f0bc13 d7b63b0 6f0bc13 d7b63b0 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | import os
import gradio as gr
import base64
import fitz
import docx
from huggingface_hub import InferenceClient
# 1. 核心引擎:Qwen2.5-VL-72B-Instruct (满血视觉+逻辑)
model_id = "Qwen/Qwen2.5-VL-72B-Instruct"
hf_token = os.getenv("HF_TOKEN")
client = InferenceClient(model=model_id, token=hf_token)
def extract_text(file_path):
if not file_path: return ""
try:
ext = str(file_path).lower()
if ext.endswith(".pdf"):
doc = fitz.open(file_path)
text = "".join([page.get_text() for page in doc])
doc.close()
return text[:15000]
elif ext.endswith(".docx"):
doc = docx.Document(file_path)
return "\n".join([p.text for p in doc.paragraphs])[:15000]
elif ext.endswith(".txt"):
with open(file_path, 'r', encoding='utf-8', errors='ignore') as f:
return f.read()[:15000]
return ""
except:
return ""
def chat_fn(message, history):
messages = [{"role": "system", "content": "You are the OpenIPOS MegaNode Vision & Document Expert. Analyze the provided image or text document with extreme precision."}]
for turn in history:
messages.append({"role": turn["role"], "content": str(turn["content"])})
prompt_text = message.get("text", "")
files = message.get("files", [])
content = []
if files:
for f in files:
file_path = f.get("path") if isinstance(f, dict) else f
ext = str(file_path).lower()
# 路径 A:如果是图片,走视觉协议
if ext.endswith(('.png', '.jpg', '.jpeg', '.webp', '.bmp')):
with open(file_path, "rb") as img_file:
b64 = base64.b64encode(img_file.read()).decode('utf-8')
content.append({"type": "image_url", "image_url": {"url": f"data:image/jpeg;base64,{b64}"}})
# 路径 B:如果是文档,先提词再合并成文本
else:
doc_text = extract_text(file_path)
if doc_text:
prompt_text = f"【文档参考内容】:\n{doc_text}\n\n【用户指令】: {prompt_text}"
content.append({"type": "text", "text": prompt_text})
messages.append({"role": "user", "content": content})
response = ""
try:
stream = client.chat_completion(messages, max_tokens=4096, stream=True, temperature=0.4)
for msg in stream:
if hasattr(msg, 'choices') and len(msg.choices) > 0:
delta = msg.choices[0].delta.content
if delta:
response += str(delta)
yield response
if response:
yield response + "\n\n---\n> **Powered by OpenIPOS Global 算力节点 | 访问 api.openipos.com 获取私有部署**"
except Exception as e:
yield f"⚠️ 算力调度异常: {str(e)}。若文档过大,请尝试截取核心部分上传。"
# 3. 旗舰界面
with gr.Blocks(fill_height=True) as demo:
gr.HTML("""
<div style="display: flex; align-items: center; gap: 20px; padding: 10px;">
<img src="https://s3.bmp.ovh/2026/03/30/rIAGKg0O.png" style="height: 60px; width: auto;">
<div>
<h1 style="margin: 0; font-size: 24px;">OpenIPOS MegaNode</h1>
<p style="margin: 0; color: #666;">全球顶尖 72B 视觉+文档全模态算力出口 (Qwen2.5-VL)</p>
</div>
</div>
""")
gr.ChatInterface(chat_fn, multimodal=True)
gr.Markdown("© 2026 OpenIPOS Global Limited. 算力驱动:Hugging Face 72B Cluster")
demo.launch() |