restful_api.md 5.18 KB
Newer Older
AllentDan's avatar
AllentDan committed
1
2
3
4
5
6
7
# Restful API

### 启动服务

运行脚本

```shell
8
python3 -m lmdeploy.serve.openai.api_server ./workspace 0.0.0.0 server_port --instance_num 32 --tp 1
AllentDan's avatar
AllentDan committed
9
10
```

11
然后用户可以打开 swagger UI: `http://{server_ip}:{server_port}` 详细查看所有的 API 及其使用方法。
AllentDan's avatar
AllentDan committed
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
我们一共提供四个 restful api,其中三个仿照 OpenAI 的形式。不过,我们建议用户用我们提供的另一个 API: `generate`
它有更好的性能,提供更多的参数让用户自定义修改。

### python

这是一个 python 示例,展示如何使用 `generate`

```python
import json
import requests
from typing import Iterable, List


def get_streaming_response(prompt: str,
                           api_url: str,
                           instance_id: int,
                           request_output_len: int,
                           stream: bool = True,
                           sequence_start: bool = True,
                           sequence_end: bool = True,
                           ignore_eos: bool = False) -> Iterable[List[str]]:
    headers = {'User-Agent': 'Test Client'}
    pload = {
        'prompt': prompt,
        'stream': stream,
        'instance_id': instance_id,
        'request_output_len': request_output_len,
        'sequence_start': sequence_start,
        'sequence_end': sequence_end,
        'ignore_eos': ignore_eos
    }
    response = requests.post(
        api_url, headers=headers, json=pload, stream=stream)
    for chunk in response.iter_lines(
            chunk_size=8192, decode_unicode=False, delimiter=b'\0'):
        if chunk:
            data = json.loads(chunk.decode('utf-8'))
            output = data['text']
            tokens = data['tokens']
            yield output, tokens


for output, tokens in get_streaming_response(
55
        "Hi, how are you?", "http://{server_ip}:{server_port}/generate", 0,
AllentDan's avatar
AllentDan committed
56
57
58
59
        512):
    print(output, end='')
```

60
### Java/Golang/Rust
AllentDan's avatar
AllentDan committed
61

62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
可以使用代码生成工具 [openapi-generator-cli](https://github.com/OpenAPITools/openapi-generator-cli)`http://{server_ip}:{server_port}/openapi.json` 转成 java/rust/golang 客户端。
下面是一个使用示例:

```shell
$ docker run -it --rm -v ${PWD}:/local openapitools/openapi-generator-cli generate -i /local/openapi.json -g rust -o /local/rust

$ ls rust/*
rust/Cargo.toml  rust/git_push.sh  rust/README.md

rust/docs:
ChatCompletionRequest.md  EmbeddingsRequest.md  HttpValidationError.md  LocationInner.md  Prompt.md
DefaultApi.md             GenerateRequest.md    Input.md                Messages.md       ValidationError.md

rust/src:
apis  lib.rs  models
```
AllentDan's avatar
AllentDan committed
78
79
80
81
82
83
84
85

### cURL

cURL 也可以用于查看 API 的输出结果

查看模型列表:

```bash
86
curl http://{server_ip}:{server_port}/v1/models
AllentDan's avatar
AllentDan committed
87
88
89
90
91
```

使用 generate:

```bash
92
curl http://{server_ip}:{server_port}/generate \
AllentDan's avatar
AllentDan committed
93
94
  -H "Content-Type: application/json" \
  -d '{
95
96
    "prompt": "Hello! How are you?",
    "instance_id": 1,
AllentDan's avatar
AllentDan committed
97
98
99
100
101
102
103
104
    "sequence_start": true,
    "sequence_end": true
  }'
```

Chat Completions:

```bash
105
curl http://{server_ip}:{server_port}/v1/chat/completions \
AllentDan's avatar
AllentDan committed
106
107
108
109
110
111
112
113
114
115
  -H "Content-Type: application/json" \
  -d '{
    "model": "internlm-chat-7b",
    "messages": [{"role": "user", "content": "Hello! Ho are you?"}]
  }'
```

Embeddings:

```bash
116
curl http://{server_ip}:{server_port}/v1/embeddings \
AllentDan's avatar
AllentDan committed
117
118
119
120
121
122
123
  -H "Content-Type: application/json" \
  -d '{
    "model": "internlm-chat-7b",
    "input": "Hello world!"
  }'
```

124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
### CLI client

restful api 服务可以通过客户端测试,例如

```shell
# restful_api_url 就是 api_server 产生的,比如 http://localhost:23333
python -m lmdeploy.serve.openai.api_client restful_api_url
```

### webui

也可以直接用 webui 测试使用 restful-api。

```shell
# restful_api_url 就是 api_server 产生的,比如 http://localhost:23333
# server_ip 和 server_port 是用来提供 gradio ui 访问服务的
# 例子: python -m lmdeploy.serve.gradio.app http://localhost:23333 localhost 6006 --restful_api True
python -m lmdeploy.serve.gradio.app restful_api_url server_ip --restful_api True
```

AllentDan's avatar
AllentDan committed
144
145
146
147
148
149
150
151
### FAQ

1. 当返回结果结束原因为 `"finish_reason":"length"`,这表示回话长度超过最大值。
   请添加 `"renew_session": true` 到下一次请求中。

2. 当服务端显存 OOM 时,可以适当减小启动服务时的 `instance_num` 个数

3. 当同一个 `instance_id` 的请求给 `generate` 函数后,出现返回空字符串和负值的 `tokens`,应该是第二次问话没有设置 `sequence_start=false`
AllentDan's avatar
AllentDan committed
152
153
154
155
156
157
158
159
160

4. 如果感觉请求不是并发地被处理,而是一个一个地处理,请设置好以下参数:

   - 不同的 instance_id 传入 `generate` api。否则,我们将自动绑定会话 id 为请求端的 ip 地址编号。
   - 设置 `stream=true` 使模型在前向传播时可以允许其他请求进入被处理

5. `generate` api 和 `v1/chat/completions` 均支持多轮对话。`messages` 或者 `prompt` 参数既可以是一个简单字符串表示用户的单词提问,也可以是一段对话历史。
   两个 api 都是默认开启多伦对话的,如果你想关闭这个功能,然后在客户端管理会话记录,请设置 `sequence_end: true` 传入 `generate`,或者设置
   `renew_session: true` 传入 `v1/chat/completions`