LMDeploy实战:开源大模型量化、推理与OpenAI兼容服务部署
这段时间一直在折腾开源大模型的落地部署,试了不少推理框架,最后在业务环境里稳定跑下来的是 LMDeploy。如果你也在做类似的事情——想把 Qwen、Llama 这类开源模型接到自己的系统里,或者想在项目里做一个带 API 的聊天服务,那么这篇文章应该能省下你不少折腾的时间。 LMDeploy 不是一个简单的模型加载脚本,它把量化、推理、服务三个环节串成了一条线。也就是说,你不需要先拿一个框架做量化、再换一个框架做推理、最后再单独写一个 HTTP 包装层。它自己就把这些事都干了。我这次用它在内网环境里部署了一个 7B 级别的中文模型,从下载权重到对外提供 OpenAI 风格的接口,整个流程走下来很顺。文章会按照我实际操作的过程来写,适合有一定 Python 基础、打算把开源模型真正跑起来的同学参考。

1. 为什么选 LMDeploy 做模型落地

1.1 部署开源模型绕不开的三个痛点

先说我自己遇到的情况。之前用一枚 7B 模型做验证,FP16 权重大概 15GB,单张卡勉强能加载,但一旦开并发,显存直接见底,系统动不动就 OOM。这是第一个痛点:显存不够放、放得下也跑不动。

第二个痛点是吞吐。模型加载起来只是开始,生产环境要面对的是多个用户同时请求。如果没有做动态批处理,每一次请求都独占显卡算一遍,资源利用率低得吓人。手动拼 batch 又很麻烦,因为不同请求到达时间不一样,强行等一批再算,延迟又上去了。

第三个痛点是全链路工具碎。量化是一套工具,推理是另一套工具,暴露 API 还要自己写中间层。中间只要有一个环节版本对不上,整个流程就卡住了。我需要的是一个集成度足够高的工具包,而不是一堆需要自己拼装的零件。

1.2 和其他推理框架的对比

我在选型阶段简单做过一轮对比,下面的表是我当时整理的思路。

对比维度LMDeployvLLMTGIllama.cpp
量化能力内置 AWQ/GPTQ偏弱,需外部配合偏弱支持较好
OpenAI 兼容 API开箱即用开箱即用开箱即用需额外封装
动态批处理TurboMind 原生支持PagedAttention 支持支持较弱
GPU 吞吐表现高高中低(偏 CPU)
上手门槛中低中中低

vLLM 的吞吐确实强,但量化不是它的强项,我需要 AWQ 量化,用 vLLM 的话还得额外搞一套量化工具链。TGI 部署很标准,但对非主流显卡的支持一般。llama.cpp 在 CPU 场景很强,可我要的是 GPU 高吞吐,它不太合适。LMDeploy 把量化、推理、服务三者合在一起,这一点对我来说是决定性的。

1.3 它到底解决了什么问题

LMDeploy 的核心是 TurboMind 引擎。你可以把它理解成一个专门为大模型推理调优过的执行引擎,它会在内部做连续批处理和显存管理,不需要你干预。

其次,量化工具是内置的。用lmdeploy lite子命令就能做 AWQ 4bit、GPTQ 8bit 量化,量化完的模型直接给推理引擎用。我实测一个 7B 模型从 FP16 压到 4bit,显存占用能降到原来的三分之一左右,这对单卡部署来说是质变。

再一个是服务化能力。lmdeploy serve api_server一条命令就能起一个 OpenAI 兼容的服务,接口路径和参数格式都对齐 OpenAI,业务端不用改 SDK 就能切过来。这一点在接现有系统时特别省事。

2. 环境准备与安装

2.1 硬件需求与显存评估

部署之前先搞清楚自己的显卡能跑什么规模的模型。我按自己的经验给一个参考表:

模型规模精度权重显存约推理时总显存建议
7BFP1614~15GB24GB
7BW4A164~5GB12GB
13BFP1626~28GB40GB
13BW4A167~8GB16~24GB
70BW4A1635GB+多卡 80GB

注意权重显存不等于实际占用。推理过程中还有 KV Cache、激活值这些额外开销,所以表里给的“总显存建议”会宽松一些。我用的是一张 24GB 的显卡,7B 模型做 4bit 量化后跑得非常宽裕。

确认环境用两个命令就行:

nvidia-smi python -c "import torch; print(torch.version.cuda)"

确保显卡驱动、CUDA 版本和后面安装的 PyTorch 是匹配的。强烈建议先用nvidia-smi看一下驱动支持的 CUDA 版本,再决定 PyTorch 版本,不然装完 CUDA 不可用,排查起来很折磨人。

2.2 创建环境并安装 LMDeploy

我习惯先用 Conda 开一个干净环境,避免和项目里的其他依赖冲突。

conda create -n lmdeploy python=3.10 -y conda activate lmdeploy

Python 版本建议选 3.10 或 3.11,太新的版本有些依赖轮子还没跟上。然后直接安装:

pip install lmdeploy

安装过程中会带上推理需要的相关依赖。如果你只需要在 CPU 上跑跑看,可以装 CPU 版本,但实际做服务部署肯定还是要 GPU 版本。

装完之后验证一下:

lmdeploy --help

如果能正常打印出子命令列表,说明基本环境没问题。

2.3 安装时的几个坑

我第一次装的时候遇到了 FlashAttention 相关的编译报错。后来发现是 CUDA 版本和 PyTorch 版本不匹配导致的。解决方法是先把 PyTorch 装对,再装 LMDeploy,顺序反了容易踩雷。

另外要注意,lmdeploy升级很频繁,不同版本之间某些参数名会变。我建议装完之后锁定版本:

pip freeze | grep lmdeploy

记录下当前版本号,后续如果升级,一定要先看官方文档的变更说明,否则之前能跑通的脚本可能突然报参数解析错误。

还有一个很容易踩的坑:环境里如果已经有旧版的transformers,可能会和 LMDeploy 要求的版本冲突。建议在新环境里装的时候,先不装乱七八糟的东西,直接装 LMDeploy,缺什么再补什么。

3. 模型准备与量化

3.1 拉取开源模型

模型下载这一步,国内环境我优先推荐用 ModelScope,速度比直接连 HuggingFace 快很多。安装好客户端后执行:

pip install modelscope modelscope download --model Qwen/Qwen2-7B-Instruct --local_dir ./models/qwen2-7b-instruct

HuggingFace 用户也可以继续用huggingface-cli download拉权重,命令类似。下载前确认模型协议允许商用,这点在业务环境里很重要。

这里有一个小经验:下载时认准-Instruct或-Chat后缀的版本,这些是对齐了对话格式的权重。如果你拿基座模型直接做对话,没有经过对话模板处理,回答会非常奇怪。

3.2 格式转换与 TurboMind 的关系

模型从 HuggingFace 或 ModelScope 拉下来之后,原生是 safetensors 格式。LMDeploy 在加载模型时,会把它转换成自己的 TurboMind 格式来跑,转换过程会自动完成。你也可以提前手动转换:

lmdeploy convert ./models/qwen2-7b-instruct --dst-path ./models/qwen2-7b-turbomind

提前转换的价值在于,把格式转换的时间消耗从启动过程里挪走,服务上线时启动速度更快。批量部署多台机器时,也可以只转换一次,然后把 TurborMind 格式目录分发到其他机器。

3.3 AWQ 4bit 量化实操

量化的价值,再说直白一点:把模型权重从 16bit 降到 4bit,显存占用和计算量都大幅下降,而精度损失控制在可接受范围内。LMDeploy 里做 AWQ 量化用这一条命令:

lmdeploy lite auto_awq ./models/qwen2-7b-instruct --work-dir ./models/qwen2-7b-awq --batch-size 32

这里有几个参数值得解释:

  • --work-dir是量化后模型的输出目录。
  • --batch-size是校准数据的批次大小,显存足够时尽量调大,校准效果更好。
  • AWQ 量化本身需要一个校准数据集,工具会默认拉取一批公开的校准数据,如果你有自己业务领域的样本数据,替换掉默认校准集会更好。

我实际测下来,7B 模型 AWQ 量化后,显存占用从 15GB 左右降到 5GB 出头,生成速度反而比 FP16 快了一截。所以在 GPU 资源有限的场景里,量化不是“将就”,而是一个更优的策略。

量化完不用再做额外处理,LMDeploy 的推理引擎和 API 服务都能直接加载这个 4bit 模型目录。

4. 本地推理与服务部署

4.1 命令行对话模式

模型准备好之后,先跑一个快速验证,确认权重没问题:

lmdeploy chat turbomind ./models/qwen2-7b-awq --session-len 8192

--session-len是上下文长度。7B 模型 8K 上下文比较稳妥,如果你要处理超长文档,可以调大,但同时要留意显存变化。

看到提示符之后,直接输入中文问几个问题,比如让它写一段代码、总结一段文字。这一步能快速发现两个问题:量化出的模型到底能不能用、对话模板是否正常。如果连命令行对话都不对劲,就没必要往下部署了。

4.2 用 Python 接入模型

命令行验证通过后,下一步是把模型接进 Python 应用。LMDeploy 提供了 pipeline 接口:

from lmdeploy import pipeline, TurbomindEngineConfig engine_config = TurbomindEngineConfig( session_len=8192, cache_max_entry_count=0.8, ) pipe = pipeline("./models/qwen2-7b-awq", backend_config=engine_config) response = pipe("用一句话解释什么是动态批处理") print(response.text)

cache_max_entry_count控制显存中 KV Cache 的占用比例。我建议不要设满,留一点余量给显存波动。0.8 是一个比较稳的起点。

pipeline 接口还支持批量传参:

responses = pipe([ "介绍一下LMDeploy", "写一首关于秋天的诗", ]) for item in responses: print(item.text)

这里要注意,传列表进去,框架内部会自动做动态批处理,而不是简单的循环逐条执行。并发请求多的时候,这个能力直接决定吞吐上限。

4.3 一键启动 OpenAI 兼容服务

最让我省心的是这一步。命令行里执行:

lmdeploy serve api_server ./models/qwen2-7b-awq \ --server-port 8080 \ --session-len 8192 \ --cache-max-entry-count 0.8

服务起来后,用curl验证一下:

curl http://localhost:8080/v1/chat/completions \ -H "Content-Type: application/json" \ -d '{ "model": "qwen2-7b", "messages": [{"role": "user", "content": "你好"}] }'

返回的 JSON 结构和 OpenAI 的完全一致。这意味着你现有的业务代码,只要配一个 base_url 就能把模型服务从云端切到内网,不需要改请求格式。

Python 端也可以用 OpenAI SDK 直接连:

from openai import OpenAI client = OpenAI( base_url="http://localhost:8080/v1", api_key="not-needed", ) completion = client.chat.completions.create( model="qwen2-7b", messages=[{"role": "user", "content": "你好"}], ) print(completion.choices[0].message.content)

这一步做完,整个服务就相当于上线了。我实际部署时,前后跑了不到半小时就把一个 7B 模型从权重变成了可对外服务的 API。

5. 多卡部署与性能调优

5.1 张量并行部署

如果你手头是多卡机器,或者模型的体量已经超出单卡显存,LMDeploy 支持张量并行部署:

lmdeploy serve api_server ./models/qwen2-70b-awq \ --tp 2 \ --server-port 8080

--tp 2表示把模型切到两张卡上并行推理,默认是 0 卡开始。70B 模型做 4bit 量化后,单卡 80G 能勉强装下,但数据和并发一上来就吃力。用--tp 2切到两张卡,单卡压力小很多,并发也更稳。

张量并行的原理是把 Transformer 层的计算分布到多张卡上,每张卡只存一部分权重,计算过程中卡之间要通信交换中间结果。所以多卡之间如果是 NVLink 或者高速互联,性能会很好;如果是普通 PCIe 连接,性能会有折损,但比单卡 OOM 强。

5.2 核心性能参数怎么调

我调试时最常用的几个参数,逐个说明:

session_len控制上下文窗口长度。如果业务是短问答为主,不需要开太大,开大了 KV Cache 会吃掉大量显存。

cache_max_entry_count控制 KV Cache 占显存的比例。这个值设得越高,能同时服务的请求数越多,但留给权重和激活值的空间就越少。我建议从 0.8 开始,观察显存占用再微调。

max_batch_size控制单次推理的最大 batch。TurboMind 本身有动态批处理,不开这个参数也能工作,但如果你明确知道业务峰值,可以设置一个上限避免显存被冲爆。

参数推荐值说明
session_len4096~8192短对话用低值
cache_max_entry_count0.8可从 0.9 开始往下调
max_batch_size32~64按显存余量调整

性能调优是一个试出来的过程,没有万能参数。但套路是固定的:先跑少量请求观察显存和延迟,再逐步加并发,找到性能拐点。

6. 常见问题与排查实录

6.1 显存不够用,爆 OOM 怎么办

这是最普遍的一个问题。排查步骤我按经验排序:

  1. 先看nvidia-smi确认显存是被谁占的,是不是有其他进程残留。
  2. 检查session_len,上下文越长 KV Cache 越大。
  3. 调低cache_max_entry_count,从 0.8 调到 0.6 或者更低。
  4. 如果还不行,模型本身就需要量化或者换更小的模型。

另外,有些环境里会出现显存碎片化的问题,服务跑一阵子后显存碎片变多,新的分配请求失败。这种情况重启服务是最快的解决办法,生产环境可以考虑定时在低峰期重启。

6.2 量化后效果明显变差

AWQ 量化之后模型效果变差,首先怀疑校准数据质量。默认的校准数据是通用文本,如果你的业务是代码生成或者数学推理,建议提供一批真实业务样本来做校准。

我做量化的经验是,校准数据集要和实际使用场景尽量接近,样本数量在 128 条以上效果比较稳。--batch-size不要开太小,校准的时候显存允许就尽量用大 batch。

如果真的压不住精度损失,可以考虑 W4A16 的机制,也就是权重用 4bit、激活值保留 16bit——LMDeploy 的 AWQ 量化默认就是这么工作的,比连激活值一起压的“纯 4bit”要稳得多。如果还是不满意,退回 8bit GPTQ:

lmdeploy lite auto_gptq ./models/qwen2-7b-instruct --work-dir ./models/qwen2-7b-gptq

6.3 API 服务起不来或者请求报错

最常见的原因:

  • 端口被占用了,换一个--server-port。
  • 模型路径不对,启动时一定要指向模型目录本身,而不是它的上一级目录。
  • 模型名称不匹配,虽然 OpenAI 兼容接口里的model字段不一定严格校验,但有些客户端会校验,保持和模型目录名一致最省事。
  • 并发请求过大时出现 502 之类的错误,多半是显存被占满了,按 6.1 的步骤调参。

6.4 版本兼容性问题

lmdeploy版本更新快,命令和参数都有变动。我吃过一次亏:旧版本里--cache-max-entry-count能直接用,升级之后这个参数仍然可用,但某些引擎参数名称变了。遇到这种问题,先看版本:

lmdeploy --version

然后去官方文档或者 GitHub 的 release 说明里比对参数变化。不要盲目相信网上旧的教程命令,版本之间的命令差异是导致部署失败的高频原因。

还有一个容易被忽视的点:transformers版本不要随意升降级。LMDeploy 内部依赖它做 Tokenizer 和模型加载,版本不匹配会在启动时给出难懂的报错。如果遇到tokenizer相关报错,先查这一层的版本。

7. 结尾

我在实际部署中的体会是,LMDeploy 最舒服的一点就是它把“量化—推理—服务化”串成了闭环,你不需要在多个工具之间来回切换。第一次跑通的时候,我从下载权重到启动 OpenAI 兼容服务,大概用了不到一小时,这个效率在以前的工具链里很难想象。

最后再分享一个小技巧:如果你的显卡是 24G 显存,部署 7B 模型做量化后,cache_max_entry_count调到 0.85 左右,在保证稳定性的前提下并发性能会比默认设置好不少。我跑过一轮压力测试,并发从 8 加到 32,延迟增长依然可控。这个参数值得反复试,找到你自己硬件的最佳值。下次遇到部署相关的问题,欢迎回来交流,这篇里的每一条经验都是实测过的。

相关新闻

Windows cmd进入指定目录全攻略:cd命令、跨盘符与批处理技巧

Windows cmd进入指定目录全攻略:cd命令、跨盘符与批处理技巧

Windows 下在 cmd 里进指定目录,这事看起来简单到不值一提,但实际操作中我见过太多人在这一步卡住——输入cd D:\某文件夹没反应,路径一长就报错,带空格的目录怎么都进不去,还有一个很经典的cd后提示「不是内部或外部命…

2026/10/20 20:58:45 阅读更多 →
LMDeploy 大模型部署实战:从模型量化到API服务全流程指南

LMDeploy 大模型部署实战:从模型量化到API服务全流程指南

之前帮某开发者的“模拟项目X”做大模型部署时,我在 GPU 服务器上对比过好几套推理方案,踩完一圈坑之后,现在手里的长期方案基本固定成了 LMDeploy。如果你手里已经有一个开源对话模型,正打算放进业务里做 API 服务,或…

2026/10/20 20:58:45 阅读更多 →
TensorFlow鞋类识别实战:Fashion MNIST图像分类全流程

TensorFlow鞋类识别实战:Fashion MNIST图像分类全流程

前段时间重新整理之前的深度学习实验笔记,翻到鞋类识别(Fashion MNIST)这个项目时,觉得特别值得拿出来单独写一篇。原因很简单:很多人入门深度学习时,都会被建议先跑通手写数字识别(MNIST&#…

2026/10/20 20:57:37 阅读更多 →

最新新闻

图数据建模必知:从转导式到归纳式学习的范式切换实践

图数据建模必知:从转导式到归纳式学习的范式切换实践

前阵子接手一个图数据的用户行为预测项目,最初跑得挺顺,后来每来一批新用户,模型效果就肉眼可见地掉。一开始我以为只是特征没做好,调了一周才意识到,问题出在我用的学习范式上——我一直在一张静态图上做转导式&#…

2026/10/20 21:30:50 阅读更多 →
Docker镜像加载原理:分层、内容寻址与联合文件系统

Docker镜像加载原理:分层、内容寻址与联合文件系统

1. 从一次镜像拉取卡顿说起:为什么需要搞懂加载原理很多人用 Docker 的第一课就是docker pull,然后docker run,容器跑起来了,任务就算完成。直到某天你发现:同一个镜像,在测试机上拉取只要十几秒&#xff0…

2026/10/20 21:30:50 阅读更多 →
扩展HTTP协议实现文件夹多线程分片秒传:信创环境下的完整方案

扩展HTTP协议实现文件夹多线程分片秒传:信创环境下的完整方案

前段时间做信创改造,好几个同行都在问同一个问题:配置再高、网络再好的环境里,为什么文件夹上传还是动不动报错?仔细一看,多数系统还在用最原始的multipart/form-data一次性上传。大文件传一半断了就从头再来&#xff…

2026/10/20 21:30:50 阅读更多 →
开源AI助手OpenClaw本地部署实战:从零到跑通全流程

开源AI助手OpenClaw本地部署实战:从零到跑通全流程

先讲一个特别有画面感的场景:上周我在某个技术讨论区闲逛,有人发了一条动态,晒了一张终端截图——一个叫 OpenClaw 的项目跑起来了,正在自动整理他电脑里的文档。底下评论区有人问:"这跟网页版 AI 有啥区别&#…

2026/10/20 21:30:50 阅读更多 →
H3C策略路由PBR双出口实验:配置、验证与排错全指南

H3C策略路由PBR双出口实验:配置、验证与排错全指南

做网络的人早晚会撞上这样一个需求:内网有两条出口链路,领导指定“财务部门的流量必须走专线,其他上网流量走普通宽带”,然后你觉得这很简单,在出口设备上多写几条静态路由不就完事了吗?真正敲完命令你会发…

2026/10/20 21:30:50 阅读更多 →
大语言模型反常识推理能力:培养路径与工程实践

大语言模型反常识推理能力:培养路径与工程实践

大规模语言模型的反常识推理能力培养这两年做大模型应用,有个问题一直在困扰我和身边的同行:模型在常规问答、内容生成上已经强得离谱,但只要碰到那种"违背直觉但其实是正确答案"的问题,立马就露怯。比如你问"一个…

2026/10/20 21:29:46 阅读更多 →

日新闻

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →
ESP32舵机控制指南:原理、多路驱动与避坑实战

ESP32舵机控制指南:原理、多路驱动与避坑实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →
位移法实现一阶低通滤波:单片机ADC采样降噪实战

位移法实现一阶低通滤波:单片机ADC采样降噪实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/20 10:02:13 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/20 20:43:59 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/20 2:50:50 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 10:02:08 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 9:50:17 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 9:50:45 阅读更多 →