当调度器接收到外部请求后,会基于集群状态,计算用于服务该请求的PD实例。然后将请求发送给对应的P实例。
由于标准推理(PD混部)对外提供了五类推理接口兼容(分别是TGI、vLLM、OpenAI、Triton和MindIE原生接口),因而,在PD分离场景下,调度器需要兼容这5类接口。当调度器收到外部请求(RESTful请求)后,会向P实例转发本次请求,请求的URL和Body与PD混部保持一致,但需要在HTTP HEADER中加入部分控制信息,控制信息请参见表1。
字段名 |
是否必选 |
字段描述 |
取值类型 |
---|---|---|---|
req-id |
必选 |
全局唯一的RequestID。 |
数字类型的字符串,要求全局唯一。 |
d-target |
必选 |
目标D实例的IP地址。 |
IP地址。 |
req-type |
必选 |
请求类型。 |
固定值:prefill。 |
is-recompute |
可选(重计算场景下必选) |
是否重计算。 |
|
请求样例:
curl -i -H "req-id: 12345" -H "req-type: prefill" -H "d-target: 172.17.0.9" -H "Accept: application/json" -H "Content-type: application/json" -X POST -d ' { "model": "llama2_7b", "messages": [{ "role": "system", "content": "You are a helpful assistant." }], "max_tokens": 20, "presence_penalty": 1.03, "frequency_penalty": 1.0, "seed": null, "temperature": 0.5, "top_p": 0.95, "stream": true }' https://172.17.0.10:1025/v1/chat/completions
一个请求的响应会分别发生在P实例和D实例中,且两实例的响应内容不同。
响应体如下所示:
{ "reqId": "12345", "isStream": true, "output": "data:{...}", "isLastResp": false }
由于调度器不解析外部请求的内容(仅转发注入HTTP HEADER之后的请求),对于部分请求,无法确定是否流式(部分请求的流式/非流式在URL中能体现,但部分请求的流式/非流式只有Body中才有,目前的调度器实现中,并没有解析Body)。而针对请求是否流式,调度器对外返回的形式会有区别,因而,在P实例的响应中,直接告知是否流式。
调度器需要将推理结果响应给外部请求者,但响应的内容来自推理实例。在P响应中,响应的内容在output字段中体现。调度器不需要解析output的内容,仅需要使用合适的方式(流式、非流式,首token、唯一token、不同的接口类型等因素,会造成调度器的不同行为)返回给请求者即可。
data:{"id":"a123","model_name":"llama_65b","model_version":null,"text_output":"am","details":{"generated_tokens":1,"first_token_cost":null,"decode_cost":null,"batch_size":1,"queue_wait_time":10},"prefillTime":26.96,"decodeTime":null}
调度器与D实例间,存在一个长连接,D实例每推理出一个结果,就通过该长连接响应给调度器。
操作类型:GET
URL:https://{ip}:{port}/dresult
请求样例:
GET https://{ip}:{port}/dresult
Content-Type: text/event-stream Transfer-Encoding: chunked
单次的返回结果由2部分组成,分别是size和data。
其中,size是用16进制表示的字符串(不需要带0x),表示data的长度。data就是实际传输的内容。size和data都以\r\n结尾。
18\r\n{"aaa":"bbb","ccc":"ddd"}\r\n