零 实验软硬件环境说明
| 分类 | 项目 | 配置详情 | 备注 |
|---|
| 硬件环境 | CPU | e5 2696V3(逻辑核心数>=16) | 启动时分配 8 cores 给 Ray |
| 物理内存 (RAM) | 32 GB | 关键瓶颈,需要精细规划共享内存 |
| GPU | NVIDIA GeForce RTX 3090 x 2 | 单卡 24GB VRAM |
| 网络 | 无线网卡 (USB) | wlxe0ad47220334 |
| 操作系统 | OS 发行版 | Ubuntu 24.04 LTS | 内核版本 6.14.0-37-generic |
| 宿主机 IP | 10.193.195.59(机器正常活动网卡) | 无线网络 IP,作为集群通信地址 |
| 基础软件 | Docker 管理 | Docker Engine | 开源容器引擎 |
| NVIDIA 驱动 | 570.211.01 | 支持 CUDA 12.8 |
| Docker 网络 | Host 模式 (--network host) | 容器与宿主机共享网络栈,性能最优 |
| 核心环境 | 基础镜像 | ray-vllm:3090-cuda12.8 | 包含 Ray, vLLM, CUDA 12.8 |
| Python | 3.12.3 | Ray 脚本路径显示 |
| 集群配置 | Ray 版本 | 2.53.0 | 支持 ray metrics launch-prometheus |
| 集群架构 | Head Node + Worker Node (双容器) | ray-node-0 (Head), ray-node-1 (Worker) |
| 通信端口 | 6379 (GCS), 8265 (Dashboard), 8080 (Metrics) | 确保 6379 未被 Redis 占用 |
| 资源分配 | GPU 策略 | 独占模式 | --gpus all + NVIDIA_VISIBLE_DEVICES=0/1 |
| 共享内存 | 12 GB / 容器 | 物理内存 32GB 下的折中方案 |
| 内存优化 | Memfd 启用 | 环境变量 VLLM_USE_MEMFD=1 绕过 /dev/shm 限制 |
一 核心架构
- 宿主机(Ubuntu24.04+ 双 3090)部署2 个 Docker 容器,单容器独占 1 张 3090,通过
--gpus device=N精准绑定显卡;容器内搭建 Ray 分布式集群(1 主 1 从),基于 vLLM 实现 4B 大模型的分布式推理/部署,全程保留宿主机 3090 的可视化使用,无需 GPU 直通,兼顾开发操作与算力利用。
- 适配性:单张 3090(24G 显存)满足 8B 模型(FP16 约 16G/INT4 约 4G)的显存要求,vLLM 的 PagedAttention 技术进一步降低显存占用,双容器分布式可提升推理吞吐量/并发量。
前置条件
- 宿主机已装Ubuntu24.04 图形版,双 3090 显卡正常识别,开启基础虚拟化(BIOS 的 VMX)。
- 宿主机已装NVIDIA 官方驱动(≥535,建议 545/550),验证:
nvidia-smi能正常显示双 3090。
- 宿主机网络正常,能拉取 Docker 镜像,建议换国内镜像源。
二 Docker 和 NVIDIA Container Toolkit 准备
2.1 Docker 环境准备
- 确保宿主机已安装 Docker。若未安装,请通过官方渠道或包管理器安装 Docker Engine。
- 可以在 Docker 配置中添加镜像代理以加速拉取。
https://docker.1ms.run https://swr.cn-north-4.myhuaweicloud.com
- 拉取 NVIDIA CUDA 基础镜像。
docker pull swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/nvidia/cuda:12.8.1-cudnn-devel-ubuntu24.04
docker tag swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/nvidia/cuda:12.8.1-cudnn-devel-ubuntu24.04 docker.io/nvidia/cuda:12.8.1-cudnn-devel-ubuntu24.04
2.2 NVIDIA Container Toolkit 环境准备
- NVIDIA Container Toolkit 的配置主要参考 NVIDIA 官方文档。
sudo apt-get update
sudo apt-get install -y curl
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg
curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
sudo apt-get update
sudo apt-get install -y nvidia-container-toolkit
sudo nvidia-ctk runtime configure --runtime=docker
sudo systemctl restart docker
三 定制化 Docker 镜像
- 基于
nvidia/cuda:12.8.1-cudnn-devel-ubuntu24.04基础镜像(适配 3090,兼容 Ubuntu24.04),构建包含 Python3.10+Ray+vLLM + 依赖库的定制镜像,确保双容器环境一致,避免版本冲突。
3.1 构建镜像存放位置
mkdir -p /opt/ray-vllm && cd /opt/ray-vllm
3.2 创建 Dockerfile 文件
cd /opt/ray-vllm
vim Dockerfile
# 基础镜像:CUDA 12.8.1 + CUDNN+ Ubuntu 24.04(适配 3090,兼容 vLLM/Ray)
FROM nvidia/cuda:12.8.1-cudnn-devel-ubuntu24.04
# 第一步:修复 NVIDIA GPG 密钥警告,刷新 apt 缓存
RUN mkdir -p /etc/apt/trusted.gpg.d &&\
cp /etc/apt/trusted.gpg /etc/apt/trusted.gpg.d/nvidia-cuda.gpg &&\
apt update &&\
apt clean &&\
rm -rf /var/lib/apt/lists/*
# 第二步:安装基础依赖
RUN apt update && apt install -y --no-install-recommends \
python3-dev python3-pip \
git wget vim net-tools iputils-ping \
&& rm -rf /var/lib/apt/lists/*
# 第三步:直接配置国内 PyPI 源
RUN pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
# 第四步:安装 Ray(分布式核心,2.53.0 稳定版,兼容 Python3.11/CUDA 12.8)
RUN pip install ray[default,serve]==2.53.0 -i https://pypi.tuna.tsinghua.edu.cn/simple --break-system-packages
# 第五步:安装 vLLM(大模型推理,适配 CUDA 12.8,添加--break-system-packages 解决 ubuntu24.4 报错)
RUN pip install vllm[all] -i https://pypi.tuna.tsinghua.edu.cn/simple --break-system-packages
# 第六步:安装 PyTorch(适配 CUDA 12.8,使用官方 whl 包)
RUN pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu128 --break-system-packages &&\
pip install transformers accelerate sentencepiece -i https://pypi.tuna.tsinghua.edu.cn/simple --break-system-packages
# 第七步:设置 CUDA 12.8 环境变量,确保依赖能找到 CUDA 路径
ENV CUDA_HOME=/usr/local/cuda-12.8
ENV PATH=$CUDA_HOME/bin:$PATH
ENV LD_LIBRARY_PATH=$CUDA_HOME/lib64:$LD_LIBRARY_PATH
# 工作目录
WORKDIR /root/ray-vllm
3.3 构建 Docker 镜像
- 进入 Dockerfile 所在目录,执行构建命令,镜像命名为 ray-vllm:3090-cuda12.8。构建时间约 10 分钟,全程无报错即成功。
cd /opt/ray-vllm
docker build -t ray-vllm:3090-cuda12.8 .
3.4 启动双 Docker 容器(单容器单 3090,桥接网络)
- 创建2 个容器,分别绑定3090-0(第 1 张)和 3090-1(第 2 张)显卡,使用桥接网络(容器与宿主机/容器间同一网段,Ray 集群通信必备),同时映射端口(Ray 仪表盘/LLM 推理端口)。
- 启动主节点容器(ray-node-0)绑定 GPU 0;启动从节点容器(ray-node-1)绑定 GPU 1。执行以下命令,创建并启动主从节点容器,分别独占 3090-0 和 3090-1,桥接网络,映射 Ray(6379/8265)和 vLLM(8000)端口。
docker run -itd \
--name ray-node-0 \
--gpus device=0\
--network host\
--privileged \
--shm-size=12g \
-e VLLM_USE_MEMFD=1\
-e NVIDIA_VISIBLE_DEVICES=0\
-v /opt/ray-vllm/data-0:/root/ray-vllm/data \
ray-vllm:3090-cuda12.8 /bin/bash
docker run -itd \
--name ray-node-1 \
--gpus device=1\
--network host\
--privileged \
--shm-size=12g \
-e VLLM_USE_MEMFD=1\
-e NVIDIA_VISIBLE_DEVICES=1\
-v /opt/ray-vllm/data-1:/root/ray-vllm/data \
ray-vllm:3090-cuda12.8 /bin/bash
3.5 验证容器状态
- 说明:由于 NVIDIA Container Toolkit 的特殊机制,在但容器内使用 nvidia-smi 命令可以查看到两个 GPU,这是正常现象,但通过
env | grep NVIDIA可以验证可以使用的 GPU,重点以此来验证容器内 GPU 隔离的成功。
- 主节点容器状态验证
docker exec -it ray-node-0 bash
export CUDA_VISIBLE_DEVICES=0
python3 -c "import torch; print('Node0:', torch.cuda.device_count())"
env | grep NVIDIA
exit
(base) root@yang-server:/opt/ray-vllm# docker exec -it ray-node-0 bash
root@yang-server:~/ray-vllm# python3 -c "import torch; print('Node0:', torch.cuda.device_count())"
Node0: 2
root@yang-server:~/ray-vllm# export CUDA_VISIBLE_DEVICES=0
root@yang-server:~/ray-vllm# python3 -c "import torch; print('Node0:', torch.cuda.device_count())"
Node0: 1
root@yang-server:~/ray-vllm# env | grep NVIDIA
NVIDIA_VISIBLE_DEVICES=0
docker exec -it ray-node-1 bash
export CUDA_VISIBLE_DEVICES=1
python3 -c "import torch; print('Node1:', torch.cuda.device_count())"
env | grep NVIDIA
exit
(base) root@yang-server:~
root@yang-server:~/ray-vllm
root@yang-server:~/ray-vllm
Node1: 1
root@yang-server:~/ray-vllm
NVIDIA_VISIBLE_DEVICES=1
四 搭建 Ray 分布式集群
- 分布式集群为双容器(1 主 1 从),每个容器内只有一张 GPU 可以使用。
4.1 确定宿主机 IP(集群通信地址)
- 在宿主机终端执行 ip 地址查看命令。
ip addr
(base) root@yang-server:~# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host noprefixroute valid_lft forever preferred_lft forever
2: enp5s0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc fq_codel state DOWN group default qlen 1000 link/ether 00:e0:21:9d:65:a0 brd ff:ff:ff:ff:ff:ff
3: wlxe0ad47220334: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000 link/ether e0:ad:47:22:03:34 brd ff:ff:ff:ff:ff:ff inet 10.193.195.59/17 brd 10.193. scope global dynamic noprefixroute wlxe0ad47220334 valid_lft ec preferred_lft ec inet6 fe80:::b18:e57:fbdc/ scope link noprefixroute valid_lft forever preferred_lft forever
**10.193.195.59** (网卡 wlxe0ad47220334)
- 状态:
state UP (正在运行)
- 类型:无线网卡 (以
wl 开头)
- 理由:处于 UP 状态且拥有正常互联网 IP 地址的网卡。Ray 集群的节点之间需要通过这个 IP 进行通信。
**192.168.x.x** (有线网卡 enp5s0)
- 状态:
state DOWN (已断开)
- 理由:有线网卡目前没有连接网线或者没有获取到 IP,所以无法使用。
4.2 主节点启动 Ray Head 节点
注意关闭宿主机上 6379 端口 Redis 的服务。
- 进入主节点容器,启动 Ray Head 节点。
node-ip-address请根据实际情况使用上一步,查询到的可用 IP。
docker exec -it ray-node-0 bash
ray start --head \
--node-ip-address=10.193.195.59 \
--port=6379\
--dashboard-host=0.0.0.0 \
--num-cpus=8\
--num-gpus=1
- 启动成功标志:终端输出 Ray runtime started.,并显示从节点连接命令。
4.3 从节点容器加入 Ray 集群
- 进入从节点容器,加入 Ray 集群,
address需要填写主节点给出的连接 IP 10.193.195.59:6379。
docker exec -it ray-node-1 bash
ray start --address='10.193.195.59:6379' --node-ip-address='10.193.195.59' --num-cpus=8 --num-gpus=1
- 成功标志:终端输出
Worker node connected to head node。
4.4 验证 Ray 集群状态
docker exec -it ray-node-0 bash
ray status
root@yang-server:~/ray-vllm# ray status
======== Autoscaler status: 2026-01-29 05:14:29.925034 ========
Node status
Active: 1 node_b4f370771c977c241f30a026e0c9ddfb4ee38a38d01eb731f9f72efd
1 node_802f333067990b56926977df9b233c5fa021783653ba92413e0a36ca
Resources
Total Usage: 0.0/16.0 CPU
0.0/2.0 GPU
0B/42.89GiB memory
0B/18.38GiB object_store_memory
4.5 查看 Ray 仪表盘
可视化验证:宿主机浏览器打开http://localhost:8265,进入 Ray 仪表盘,在 Cluster 能看到 2 个节点,GPUs 显示 2,即集群搭建成功。(每个节点虽然显示两个 GPU,但实际只使用一个 GPU)
[图:Ray Dashboard 界面]
4.6 节点内验证 Ray 集群状态
- 在主节点挂载目录
/opt/ray-vllm/data-0/,创建测试脚本。
cd /opt/ray-vllm/data-0/
vim check_resources.py
import ray
ray.init(address='auto', _node_ip_address='10.193.195.59')
cluster_resources = ray.cluster_resources()
available_resources = ray.available_resources()
print("--- 集群总资源 ---")
for resource, value in cluster_resources.items():
print(f"{resource}: {value}")
print("\n--- 可用资源 ---")
for resource, value in available_resources.items():
print(f"{resource}: {value}")
nodes = ray.nodes()
print(f"\n--- 节点数量:{len(nodes)} ---")
for node in nodes:
print(f"节点 ID: {node['NodeID']}")
print(f"节点 IP: {node['NodeManagerAddress']}")
print(f"节点资源:{node['Resources']}")
print("---")
ray.shutdown()
- 执行脚本,可以清楚地看到每个容器内的 GPU 数量为 1。
root@yang-server:~/ray-vllm/data# python3 check_resources.py
2026-01-29 05:35:34,420 INFO worker.py:1821 -- Connecting to existing Ray cluster at address: 10.193.195.59:6379...
2026-01-29 05:35:34,434 INFO worker.py:1998 -- Connected to Ray cluster. View the dashboard at http://10.193.195.59:8265
/usr/local/lib/python3.12/dist-packages/ray/_private/worker.py:2046: FutureWarning: Tip: In future versions of Ray, Ray will no longer override accelerator visible devices env var if num_gpus=0 or num_gpus=None (default). To enable this behavior and turn off this error message, set RAY_ACCEL_ENV_VAR_OVERRIDE_ON_ZERO=0 warnings.warn(
--- 集群总资源 ---
object_store_memory: 19738098892.0
GPU: 2.0
CPU: 16.0
accelerator_type:G: 2.0
memory: 46055564084.0
node:10.193.195.59:
:__internal_head__:
--- 可用资源 ---
object_store_:
:
:
:.:
accelerator_::
:
:__internal_head__:
--- 节点数量: ---
--- 节点 : b4f370771c977c241f30a026e0c9ddfb4ee38a38d01eb731f9f72efd
节点 : .
节点资源:{'memory':, :, :, :, :, :, :}
--- 节点 ID: f333067990b56926977df9b233c5fa021783653ba92413e0a36ca
节点 IP: .
节点资源:{'memory':, :, :, :, :, :}
---
五 模型下载和运行
5.1 下载 Qwen3-4B 模型
- 在宿主机 base 环境下,执行命令下载模型。
cd /opt/ray-vllm/data-0/
pip install modelscope
modelscope download --model Qwen/Qwen3-4B-Instruct-2507 --local_dir ./Qwen3-4B-Instruct-2507
- 验证容器内可访问模型
docker exec -it ray-node-0 bash
cd /root/ray-vllm/data
ls -l
5.2 Ray+vLLM 分布式运行 Qwen3-4B 大模型
docker exec -it ray-node-0 bash
cd /root/ray-vllm/data
vllm serve ./Qwen3-4B-Instruct-2507 \
--tensor-parallel-size 2\
--gpu-memory-utilization 0.75\
--max-model-len 4096\
--host 0.0.0.0 \
--port 8000
5.3 查看 GPU 运行状态
pip install nvitop
nvitop -m full
[图:GPU 监控界面]
六 交互式分布式推理(快速测试)
6.1 脚本测试
docker exec -it ray-node-0 bash
cd /root/ray-vllm/data
vim test.py
from openai import OpenAI
client = OpenAI(
base_url="http://127.0.0.1:8000/v1",
api_key="dummy"
stream = client.chat.completions.create(
model="./Qwen3-4B-Instruct-2507",
messages=[{"role":"system","content":"你是一个有用的助手。"},{"role":"user","content":"请写一首七言绝句,赞美伟大的领袖。要求:磅礴大气,情感深厚。"}],
temperature=0.7,
max_tokens=3072,
stream=True,
for chunk in stream:
if chunk.choices and chunk.choices[0].delta.content is not None:
print(chunk.choices[0].delta.content, end="", flush=True)
print()
python3 test.py
万里江山披赤帜,千秋伟业铸雄魂。风雷激荡开新纪,一炬长明照乾坤。 ——此诗以'万里江山''千秋伟业'展现宏阔气度,以'风雷激荡''一炬长明'抒发深沉敬意,赞颂领袖胸怀天下、扭转乾坤的非凡气魄,情感磅礴,气象雄浑。
(APIServer pid=1217) INFO: 127.0.0.1:50880 - "POST /v1/chat/completions HTTP/1.1"200 OK
(APIServer pid=1217) INFO 01-29 14:14:23 [loggers.py:257] Engine 000: Avg prompt throughput: 4.0 tokens/s, Avg generation throughput: 14.7 tokens/s, Running: 0 reqs, Waiting: 0 reqs, GPU KV cache usage: 0.0%, Prefix cache hit rate: 0.0%
6.2 网页对话交互测试
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AI 对话助手 (vLLM)</title>
<style>
:root{--primary-color: #4f46e5;/* 靛蓝色 */--primary-hover: #4338ca;--bg-color: #f3f4f6;--chat-bg: #ffffff;--text-main: #111827;--text-secondary: #6b7280;--border-color: #e5e7eb;--user-bubble-bg: #4f46e5;--user-bubble-text: #ffffff;--ai-bubble-bg: #f9fafb;--ai-bubble-text: #1f2937;--shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);--shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);}
*{box-sizing: border-box;margin: 0;padding: 0;}
body{font-family: -apple-system, BlinkMacSystemFont,"Segoe UI", Roboto, Helvetica, Arial, sans-serif;background-color:var(--bg-color);color:var(--text-main);height: 100vh;display: flex;flex-direction: column;overflow: hidden;/* 防止整个页面滚动 */}
/* 顶部导航 */header{background:var(--chat-bg);padding: 1rem 1.5rem;border-bottom: 1px solid var(--border-color);display: flex;justify-content: space-between;align-items: center;flex-shrink: 0;z-index: 10;}.brand{font-size: 1.25rem;font-weight: 700;color:var(--text-main);display: flex;align-items: center;gap: 0.5rem;}.brand svg{color:var(--primary-color);}.settings-toggle{background: transparent;border: 1px solid var(--border-color);padding: 0.5rem;border-radius: 0.5rem;cursor: pointer;color:var(--text-secondary);transition: all 0.2s;}.settings-toggle:hover{background:var(--bg-color);color:var(--text-main);}
/* 设置面板(可折叠) */#settings-panel{background:var(--chat-bg);border-bottom: 1px solid var(--border-color);padding: 1rem 1.5rem;display: none;/* 默认隐藏 */grid-template-columns:repeat(auto-fit,minmax(200px, 1fr));gap: 1rem;animation: slideDown 0.3s ease-out;flex-shrink: 0;}#settings-panel.open{display: grid;}@keyframes slideDown{from{opacity: 0;transform:translateY(-10px);}to{opacity: 1;transform:translateY(0);}}.input-group{display: flex;flex-direction: column;gap: 0.25rem;}.input-group label{font-size: 0.75rem;font-weight: 600;color:var(--text-secondary);text-transform: uppercase;letter-spacing: 0.05em;}.input-group input{padding: 0.5rem;border: 1px solid var(--border-color);border-radius: 0.375rem;font-size: 0.875rem;outline: none;transition: border-color 0.2s;}.input-group input:focus{border-color:var(--primary-color);box-shadow: 0 0 0 2px rgba(79, 70, 229, 0.1);}
/* 聊天主区域 */#chat-container{flex: 1;overflow-y: auto;padding: 1.5rem;display: flex;flex-direction: column;gap: 1.5rem;scroll-behavior: smooth;}.message-wrapper{display: flex;gap: 1rem;max-width: 800px;margin: 0 auto;width: 100%;animation: fadeIn 0.3s ease-out;}@keyframes fadeIn{from{opacity: 0;transform:translateY(5px);}to{opacity: 1;transform:translateY(0);}}.avatar{width: 36px;height: 36px;border-radius: 6px;flex-shrink: 0;display: flex;align-items: center;justify-content: center;font-size: 1.2rem;}.user-msg .message-wrapper{flex-direction: row-reverse;}.user-msg .avatar{background:var(--user-bubble-bg);color: white;}.ai-msg .avatar{background: #10a37f;/* ChatGPT 绿色风格 */color: white;}.message-content{padding: 0.75rem 1rem;border-radius: 12px;font-size: 1rem;line-height: 1.6;position: relative;word-wrap: break-word;max-width: 85%;white-space: pre-wrap;}.user-msg .message-content{background:var(--user-bubble-bg);color:var(--user-bubble-text);border-top-right-radius: 2px;}.ai-msg .message-content{background:var(--ai-bubble-bg);color:var(--ai-bubble-text);border: 1px solid var(--border-color);border-top-left-radius: 2px;}
/* 打字动画 */.typing-indicator{display: flex;gap: 4px;padding: 4px 0;}.typing-dot{width: 6px;height: 6px;background: #9ca3af;border-radius: 50%;animation: bounce 1.4s infinite ease-in-out both;}.typing-dot:nth-child(1){animation-delay: -0.32s;}.typing-dot:nth-child(2){animation-delay: -0.16s;}@keyframes bounce{0%, 80%, 100%{transform:scale(0);}40%{transform:scale(1);}}
/* 底部输入区 */.input-area{background:var(--chat-bg);padding: 1.5rem;border-top: 1px solid var(--border-color);flex-shrink: 0;}.input-box-wrapper{max-width: 800px;margin: 0 auto;position: relative;background: #fff;border: 1px solid var(--border-color);border-radius: 0.75rem;box-shadow:var(--shadow-sm);transition: box-shadow 0.2s, border-color 0.2s;display: flex;align-items: flex-end;padding: 0.5rem;}.input-box-wrapper:focus-within{border-color:var(--primary-color);box-shadow:var(--shadow-md);}textarea{flex: 1;border: none;resize: none;padding: 0.75rem;font-size: 1rem;font-family: inherit;max-height: 200px;min-height: 24px;outline: none;background: transparent;line-height: 1.5;}.send-btn{background:var(--primary-color);color: white;border: none;border-radius: 0.5rem;width: 36px;height: 36px;display: flex;align-items: center;justify-content: center;cursor: pointer;margin-bottom: 2px;margin-right: 2px;transition: background 0.2s;}.send-btn:hover{background:var(--primary-hover);}.send-btn:disabled{background: #d1d5db;cursor: not-allowed;}
/* 滚动条美化 */#chat-container::-webkit-scrollbar{width: 8px;}#chat-container::-webkit-scrollbar-track{background: transparent;}#chat-container::-webkit-scrollbar-thumb{background-color: #d1d5db;border-radius: 4px;}#chat-container::-webkit-scrollbar-thumb:hover{background-color: #9ca3af;}
/* 响应式调整 */@media(max-width: 640px){header{padding: 0.75rem 1rem;}#chat-container{padding: 1rem;}.message-wrapper{max-width: 100%;}.message-content{max-width: 90%;font-size: 0.95rem;}.input-area{padding: 1rem;}}
vLLM Chat
API Base URL模型名称API Key
你好!我是 vLLM 助手。有什么我可以帮你的吗?
[图:网页对话界面]