uvicorn/fastapi/flash/asyncio区别
项目
类型
作用
与 asyncio 的关系
asyncio
Python标准库
提供异步编程基础
基础异步运行时
Uvicorn
ASGI服务器
运行异步Web应用
基于 asyncio 构建
FastAPI
Web框架
构建Web API
内部使用 asyncio 处理异步请求
Flask
Web框架
构建Web应用
传统同步,可搭配异步但非原生
关键区别:
asyncio 是底层异步引擎
Uvicorn 是利用 asyncio 的服务器
FastAPI 是基于 asyncio 的异步框架
Flask 是同步框架,需要额外适配才能用
asyncio
关系层级
关系层级:
1客户端请求 → Uvicorn(服务器) → FastAPI/Flask(Web框架) → 你的代码
Flask:同步WSGI框架,通常使用 Gunicorn +
Werkzeug 作为服务器
FastAPI:异步ASGI框架,通常使用
Uvicorn 作为服务器
Uvicorn 是
服务 ...
NVIDIA显卡对比
GPU 型号
架构
FP64 TFLOPS
FP32 TFLOPS
FP16 TFLOPS
INT8 TFLOPS
FP8 TFLOPS
FP4 TFLOPS
显存
显存类型
内存带宽(GB/s)
NVLink
RDMA
PCIe
CUDA 核心
TDP (W)
V100
Volta
7.8
15.7
125
250
—
—
16/32 GB
HBM2
900
300 GB/s
✓
PCIe 3.0
5120
250–300
A100
Ampere
9.7
19.5
312
624
—
—
40/80 GB
HBM2e
1555/2039
600 GB/s
✓
PCIe 4.0
6912
300–400
A800
Ampere
9.7
19.5
312
624
—
—
40 GB
HBM2
1500
400 GB/s
RTX 4090
Ada
—
82.6
165
330
330
—
24 GB
GDDR6X
1000
-
—
PCIe 4.0
16384
~450
RTX 60 ...
在sglang中,对内存的管理总共分成了三个核心组件
RadixTree
ReqToTokenPool
TokenToKVPool
三个的大概结构如下图所示:
RadixTree 前缀树,用户匹配请求的前缀,对应到vllm的paged
attention的page结构
ReqToTokenPool
请求和token的对应表,每个请求一行数据,列表示第k个token对应到TokenToKVPool的id
TokenToKVPool
token对应到kvcache的id,是一个一维超长数组,size大小就是系统存储的kvcache
tokens的总数
依靠这三个组件,相互配合就可以完成对请求的kvcache内存管理
组件使用
我们从请求调度流程的视角,看一下三大组件是怎么管理一个请求的内存声明周期的
首先是来了请求,需要在RadixTree做前缀匹配
做Prefill和Decode
请求完成后需要清空内存(减少引用计数,只有内存不够时才真的清除)
可以观察到,一个请求最后计算完成的状态下,相比计算前,三大组件的状态发生了以下改变:
ReqToTokenPoo ...
NOTE
前两节我们讲了进程的关系和每个进程的作用,和用户发送请求后的http流转流程
这一节我们接着从请求的视角,来讲router调度请求和实际执行推理
Router 是 nano-sglang 框架中的核心调度组件,负责接收来自 Tokenizer
的请求队列,管理内存池,调度 Prefill 和 Decode 操作,并将生成的 token
发送给 Detokenizer。
核心调度流程
请求接收与转换
Router 通过 exposed_step 方法接收来自 Tokenizer
的请求:
123456789def exposed_step(self, recv_reqs):
"""被异步包装的函数,recv_reqs就是zmq接收到的队列,异步执行当前的step调用推理"""
# 把请求从TokenizedGenerateReqInput格式转换成推理中的Req类型,并做一些初始化操作
for recv_req ...
563208b6680b75fe5d406519e5616e6fc6f08cfa77c43130f3ddf93ad6c4aabc4d850efad4dc9a554f3168f448489a05251c4876a3621ac44d39009c8df55cc6553811672bb17d453d794562742020fb25d49ab51f33cdb8662e81f9fa48298dcfc8fda74129894c736bd0f128a83f3d2ad84a8fd500f0cfe160160f4bcc7c37fb77ee2bf565b432a5dddf616be51cf34592f816fb90443d89c2f1010628f66594d1abc791b7d77731e420ef10695e6ec29e4e6042d43f2771493622b8b53c4fb8fe80f8057914eca7722ad7a05765168a9d159be1b61cb239d3013a5b6262fc03179300b1348c11b547d57fcf32fb64f4439bceec646fdc1 ...
无论是基于提示词还是基于api的function
call,本质上都是token的处理
基于提示词的function call
是把结构化的输出要求放到system prompts中,再对回复做function
call的正则匹配
基于api的function call
则是交给推理框架处理,请求时带上对应的tools字段,推理框架会把tools的内容做tokenizer和prompts放到一起,总之输入肯定也就是tokens,对输出则是推理框架去通过正则匹配function
call的结构化输出,匹配上了就认为是function
call的调用,返回响应finish_reason对应为function_call,如果没匹配上,就认为是普通文本输出
NOTE
下面将以sglang+qwen+非流式讲一讲sglang是怎么处理parse
function call的请求和返回的
首先是sglang启动qwen模型有加上
--tool-ca ...
NOTE
本文参考自 https://oigi8odzc5w.feishu.cn/wiki/LWqEwXNkBibT0ykrbI0cvptBnAf
基于API的Function Call大模型调用示例代码
代码示例:
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014 ...
使用docker部署easyimage图床
使用docker-compose部署
1234567891011121314151617version: '3.3'
services:
easyimage:
image: docker.1ms.run/ddsderek/easyimage:latest
container_name: easyimage
ports:
- '61021:80'
environment:
- TZ=Asia/Shanghai
- PUID=1000
- PGID=1000
- DEBUG=false
volumes:
- './data/config:/app/web/config'
- './data/i:/app/web/i'
restart: unless-stopped
typora通过picgo-core使用easyimage图床
配置picgo-core
安装和配置picgo-core:
12npm ...
TokenizerManager
流式响应架构详解
总体概览:
sequenceDiagram
participant User as 用户
participant API as FastAPI Server
participant TM as TokenizerManager
participant Router as Router进程
participant Model as Model RPC
participant Detok as Detokenizer
User->>API: POST /generate (GenerateReqInput)
API->>API: obj.post_init()
API->>TM: generate_request(obj)
TM->>TM: 第一次请求创建handle_loop
TM->>TM: tokenizer.encode(text)
TM->>TM: ...
mlp计算流程
先来看一下上图经典mlp的计算:
gate和up的proj,可以cat起来一起算
gate后有一个silu激活,激活后的值和up后的进行点乘,这两个操作也是一起做的
点乘结果给到down_proj就是最后的输出
对于非moe的mlp计算,qwen2和qwen3都一样的用的类Qwen2MLP
核心计算MergedColumnParallelLinear和RowParallelLinear就是使用torch.linear的计算,如果是tp,就是直接进行矩阵分块
12345678910111213141516171819202122232425262728293031323334353637383940414243class Qwen2MLP(nn.Module):
def __init__(
self,
hidden_size: int,
intermediate_size: int,
hidden_act: str,
quant_config: Optional[Qu ...





