网站文档怎么加图片不显示如何说服老板做网站
2026/3/24 9:01:52 网站建设 项目流程
网站文档怎么加图片不显示,如何说服老板做网站,著名的设计作品有哪些,wordpress同步社交GLM-4v-9b部署教程#xff1a;FastAPI封装GLM-4v-9b服务并添加鉴权 1. 为什么需要自己封装GLM-4v-9b服务#xff1f; 你可能已经试过Open WebUI或Ollama这类开箱即用的界面#xff0c;点几下就能和GLM-4v-9b聊天、传图问答。但真正在项目里用起来#xff0c;你会发现几个…GLM-4v-9b部署教程FastAPI封装GLM-4v-9b服务并添加鉴权1. 为什么需要自己封装GLM-4v-9b服务你可能已经试过Open WebUI或Ollama这类开箱即用的界面点几下就能和GLM-4v-9b聊天、传图问答。但真正在项目里用起来你会发现几个绕不开的问题团队多人共用一个WebUI账号谁在问什么图、改了什么设置根本没记录没有统一入口前端调用得拼URL、处理Cookie、手动传token想加个日志记录用户提问、保存图片路径、统计高频问题得改前端后端数据库一通折腾更关键的是——没有权限控制。一张敏感报表截图上传后只要知道地址任何人都能访问。这些问题靠改界面解决不了得回到服务层。而FastAPI就是目前最轻量、最清晰、最适合做这层封装的工具它自动生成API文档、天然支持异步、类型提示完善、鉴权模块成熟写50行代码就能跑起一个带登录、带图片上传、带请求限流的多模态服务。这不是“又一个部署教程”而是帮你把GLM-4v-9b真正变成你系统里的一个可管理、可审计、可集成的组件。2. 快速了解GLM-4v-9b9B参数单卡跑得动的高分辨率多模态模型glm-4v-9b 是智谱 AI 于 2024 年开源的 90 亿参数视觉-语言多模态模型可同时理解文本与图片支持中英双语多轮对话在 1120×1120 高分辨率输入下于图像描述、视觉问答、图表理解等任务中表现优于 GPT-4-turbo-2024-04-09、Gemini 1.0 Pro、Qwen-VL-Max 与 Claude 3 Opus。它不是简单拼接图文模型而是基于 GLM-4-9B 语言底座加入专用视觉编码器通过端到端训练实现图文交叉注意力对齐。这意味着它看图不是“先识别再翻译”而是真正把像素和文字放在同一个语义空间里理解。更实际的好处是原生支持1120×1120输入小字号表格、手机截图里的按钮文字、PDF中的公式细节都能清晰保留中文场景强项突出OCR识别准确率高尤其对中文混合数字/符号的财务报表、政务截图理解稳定部署门槛低INT4量化后仅9GB显存占用一块RTX 4090即可全速推理开箱即用生态好已官方适配transformers、vLLM、llama.cpp GGUF不用从头写加载逻辑。一句话总结“9B 参数单卡 24 GB 可跑1120×1120 原图输入中英双语视觉问答成绩超 GPT-4-turbo。”3. 环境准备与模型加载不依赖WebUI纯服务化启动我们不走Open WebUI那一套它本质是前端后端数据库三件套而是直接面向服务接口构建。这样更轻、更可控、更容易嵌入现有系统。3.1 基础环境与依赖安装确保你有一块NVIDIA显卡推荐RTX 4090 / A100 / L40CUDA版本12.1Python 3.10。# 创建干净虚拟环境 python -m venv glm4v-env source glm4v-env/bin/activate # Linux/macOS # glm4v-env\Scripts\activate # Windows # 安装核心依赖注意vLLM需匹配CUDA版本 pip install --upgrade pip pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121 pip install vllm0.6.3.post1 # 推荐此版本对GLM-4v-9b兼容性最佳 pip install fastapi uvicorn python-multipart python-jose[cryptography] passlib bcrypt pip install transformers accelerate safetensors注意不要安装open-webui或ollama相关包它们会引入冗余依赖和端口冲突。3.2 下载并验证模型权重GLM-4v-9b官方提供INT4量化版推荐使用9GB显存速度提升约40%# 使用huggingface-hub命令行工具推荐 pip install huggingface-hub huggingface-cli download ZhipuAI/glm-4v-9b --revision int4 --local-dir ./glm-4v-9b-int4下载完成后检查关键文件是否存在./glm-4v-9b-int4/ ├── config.json ├── model.safetensors # 主权重INT4量化 ├── tokenizer.json ├── tokenizer_config.json └── processor_config.json # 多模态处理器配置含图像预处理参数3.3 启动vLLM服务无WebUI纯API我们跳过WebUI直接用vLLM启动一个裸服务只暴露标准OpenAI兼容API# 单卡启动RTX 4090 vllm serve ZhipuAI/glm-4v-9b \ --revision int4 \ --dtype half \ --tensor-parallel-size 1 \ --gpu-memory-utilization 0.95 \ --max-model-len 8192 \ --port 8000 \ --host 0.0.0.0成功标志终端输出INFO: Uvicorn running on http://0.0.0.0:8000且无OOM报错。此时你已有一个运行中的多模态推理服务可通过curl测试curl -X POST http://localhost:8000/v1/chat/completions \ -H Content-Type: application/json \ -d { model: ZhipuAI/glm-4v-9b, messages: [ { role: user, content: [ {type: text, text: 这张图里有什么}, {type: image_url, image_url: {url: https://example.com/chart.png}} ] } ], max_tokens: 512 }提示vLLM原生支持多模态输入格式符合OpenAI API规范无需额外修改模型代码。4. FastAPI封装添加鉴权、图片上传、请求日志现在vLLM服务有了但它缺少三样关键能力身份认证、文件上传、行为审计。我们用FastAPI补上。4.1 创建主服务文件main.py# main.py from fastapi import FastAPI, UploadFile, File, Form, HTTPException, Depends, status from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm from fastapi.responses import JSONResponse from pydantic import BaseModel from typing import List, Optional, Dict, Any import aiofiles import os import time import logging from datetime import datetime, timedelta from jose import JWTError, jwt from passlib.context import CryptContext import secrets # --- 配置区生产环境请移至.env--- SECRET_KEY secrets.token_urlsafe(32) # 生成一次后固定 ALGORITHM HS256 ACCESS_TOKEN_EXPIRE_MINUTES 1440 # 24小时 UPLOAD_DIR ./uploads os.makedirs(UPLOAD_DIR, exist_okTrue) # 日志配置 logging.basicConfig( levellogging.INFO, format%(asctime)s - %(levelname)s - %(message)s, handlers[logging.FileHandler(glm4v_api.log), logging.StreamHandler()] ) logger logging.getLogger(__name__) # --- 模拟用户数据库生产环境替换为SQL/Redis--- fake_users_db { admin: { username: admin, hashed_password: $2b$12$EixZaYVK1fsbw1ZfbX3OXePaWxn96p36WQoeG6Lruj3vjPGga31lW, # bcrypt hash of admin123 disabled: False, } } # --- 安全组件 --- pwd_context CryptContext(schemes[bcrypt], deprecatedauto) oauth2_scheme OAuth2PasswordBearer(tokenUrltoken) def verify_password(plain_password, hashed_password): return pwd_context.verify(plain_password, hashed_password) def get_password_hash(password): return pwd_context.hash(password) def get_user(db, username: str): if username in db: user_dict db[username] return user_dict return None def authenticate_user(fake_db, username: str, password: str): user get_user(fake_db, username) if not user: return False if not verify_password(password, user[hashed_password]): return False return user def create_access_token(data: dict, expires_delta: Optional[timedelta] None): to_encode data.copy() if expires_delta: expire datetime.utcnow() expires_delta else: expire datetime.utcnow() timedelta(hours1) to_encode.update({exp: expire}) encoded_jwt jwt.encode(to_encode, SECRET_KEY, algorithmALGORITHM) return encoded_jwt # --- Pydantic模型 --- class ChatMessage(BaseModel): role: str content: List[Dict[str, Any]] class ChatRequest(BaseModel): messages: List[ChatMessage] max_tokens: int 512 temperature: float 0.7 class Token(BaseModel): access_token: str token_type: str class TokenData(BaseModel): username: Optional[str] None # --- FastAPI应用 --- app FastAPI( titleGLM-4v-9b API Service, descriptionFastAPI封装的GLM-4v-9b多模态服务含JWT鉴权与图片上传, version1.0.0 ) # --- 依赖获取当前用户 --- async def get_current_user(token: str Depends(oauth2_scheme)): credentials_exception HTTPException( status_codestatus.HTTP_401_UNAUTHORIZED, detail无法验证凭据, headers{WWW-Authenticate: Bearer}, ) try: payload jwt.decode(token, SECRET_KEY, algorithms[ALGORITHM]) username: str payload.get(sub) if username is None: raise credentials_exception token_data TokenData(usernameusername) except JWTError: raise credentials_exception user get_user(fake_users_db, usernametoken_data.username) if user is None: raise credentials_exception return user # --- 路由 --- app.post(/token, response_modelToken) async def login_for_access_token(form_data: OAuth2PasswordRequestForm Depends()): user authenticate_user(fake_users_db, form_data.username, form_data.password) if not user: raise HTTPException( status_codestatus.HTTP_401_UNAUTHORIZED, detail用户名或密码错误, headers{WWW-Authenticate: Bearer}, ) access_token_expires timedelta(minutesACCESS_TOKEN_EXPIRE_MINUTES) access_token create_access_token( data{sub: user[username]}, expires_deltaaccess_token_expires ) return {access_token: access_token, token_type: bearer} app.post(/v1/chat/completions) async def chat_completions( request: ChatRequest, image: Optional[UploadFile] File(None), current_user: dict Depends(get_current_user) ): start_time time.time() # 记录请求日志 logger.info(f[{current_user[username]}] 新请求 | messages{len(request.messages)} | image{bool(image)}) # 处理图片上传如果存在 image_path None if image: if not image.filename.lower().endswith((.png, .jpg, .jpeg, .webp)): raise HTTPException(status_code400, detail仅支持PNG/JPG/JPEG/WEBP格式) image_path os.path.join(UPLOAD_DIR, f{int(time.time())}_{image.filename}) async with aiofiles.open(image_path, wb) as out_file: content await image.read() await out_file.write(content) logger.info(f[{current_user[username]}] 图片已保存: {image_path}) # 构造vLLM请求体兼容OpenAI格式 vllm_payload { model: ZhipuAI/glm-4v-9b, messages: [], max_tokens: request.max_tokens, temperature: request.temperature } # 转换消息格式将图片转为base64或本地路径vLLM支持file:// for msg in request.messages: if msg.role user and isinstance(msg.content, list): new_content [] for item in msg.content: if item.get(type) image_url and image_path: # 替换为本地文件路径vLLM支持 new_content.append({ type: image_url, image_url: {url: ffile://{image_path}} }) else: new_content.append(item) vllm_payload[messages].append({role: msg.role, content: new_content}) else: vllm_payload[messages].append({role: msg.role, content: msg.content}) # 调用本地vLLM服务同步HTTP请求生产建议用httpx.AsyncClient import requests try: resp requests.post( http://localhost:8000/v1/chat/completions, jsonvllm_payload, timeout300 ) resp.raise_for_status() result resp.json() # 记录成功响应 duration time.time() - start_time logger.info(f[{current_user[username]}] 请求完成 | duration{duration:.2f}s | tokens{result.get(usage, {}).get(total_tokens, 0)}) return JSONResponse(contentresult) except requests.exceptions.RequestException as e: logger.error(f[{current_user[username]}] vLLM调用失败: {e}) raise HTTPException(status_code502, detail后端服务不可用) app.get(/health) async def health_check(): return {status: ok, timestamp: datetime.now().isoformat()}4.2 启动FastAPI服务# 启动监听8001端口与vLLM的8000端口分离 uvicorn main:app --host 0.0.0.0 --port 8001 --reload成功标志访问http://localhost:8001/docs看到自动生成的Swagger文档包含/token和/v1/chat/completions两个接口。4.3 鉴权与上传实测获取Token在Swagger页面点击/token→Try it out→ 输入usernameadmin,passwordadmin123→ Execute得到类似{access_token:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...}的token。调用多模态接口在/v1/chat/completions页面点击Authorize粘贴token在image字段上传一张本地图片如截图、图表在requestBody中填写{ messages: [ { role: user, content: [ {type: text, text: 请详细描述这张图的内容特别是所有文字信息。}, {type: image_url, image_url: {url: placeholder}} ] } ], max_tokens: 1024 }点击Execute你会看到GLM-4v-9b返回的结构化描述结果。此时你已拥有带JWT登录的API、自动图片存储、完整请求日志、与vLLM解耦的架构。5. 生产就绪建议从开发到上线的关键一步这个服务在开发环境跑通了但要进生产还有几处必须加固5.1 鉴权升级不止于admin账号用户管理将fake_users_db替换为真实数据库PostgreSQL SQLAlchemy支持注册、邮箱验证、角色分级admin/user/readonlyToken刷新增加/refresh-token接口避免用户频繁重新登录IP限制与速率控制用slowapi或fastapi-limiter限制单IP每分钟调用次数防暴力破解HTTPS强制Nginx反向代理时开启Strict-Transport-Security头。5.2 图片处理优化临时存储清理添加后台任务APScheduler自动删除24小时未被引用的上传图片安全扫描上传前用python-magic检查文件真实MIME类型防止伪装木马尺寸限制在FastAPI中校验UploadFile.size 10 * 1024 * 102410MB防大文件耗尽磁盘。5.3 vLLM服务增强健康检查探针在vLLM启动命令中加--api-key your-secret-keyFastAPI调用时带上Header多卡扩展若需更高吞吐将--tensor-parallel-size 2并绑定两张卡缓存加速启用vLLM的--enable-prefix-caching对重复图片提问提速30%。5.4 日志与监控结构化日志用structlog替代基础logging输出JSON日志便于ELK采集关键指标埋点记录request_latency_ms,tokens_per_second,error_rate_5xx接入Prometheus告警机制当连续5次vLLM调用超时自动发企业微信/钉钉告警。这些不是“锦上添花”而是让服务真正扛住业务流量的底线配置。少做一项上线后就可能多一个深夜告警电话。6. 总结你已掌握一套可落地的多模态服务封装方法论回顾整个过程你不是只学会了一个模型的部署命令而是掌握了一套可复用、可演进、可交付的服务封装方法论分层清晰vLLM专注推理性能FastAPI专注业务逻辑两者解耦各自升级互不影响安全前置鉴权不是最后加的补丁而是从第一行代码就设计好的能力可观测性强每条请求都有日志、有耗时、有Token归属出了问题3分钟定位生产就绪快所有增强点限流、清理、监控都是标准库几行代码无需重写架构。下一步你可以轻松做到把这个服务打包成Docker镜像一键部署到K8s集群对接公司SSO系统用LDAP/OAuth2替代本地账号在前端项目中用一行axios调用替代所有图片理解逻辑。技术的价值从来不在“能不能跑”而在于“能不能稳、能不能管、能不能融”。你现在手里的已经不是一个玩具模型而是一个随时能嵌入你业务系统的智能视觉引擎。获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询