File size: 10,829 Bytes
b247dc4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
# Manifest
How to make prompt programming with Foundation Models a little easier.


# Table of Contents
- [Install](#install)
- [Getting Started](#getting-started)
- [Manifest](#manifest-components)
- [Other Models Types](#other-models)
    - [Local HuggingFace Models](#local-huggingface-models)
    - [Chat Models](#chat-models)
    - [Embedding Models](#embedding-models)
- [Road Map](#road-map)
- [Development](#development)
- [Cite](#cite)


# Install
Install:
```bash
pip install manifest-ml
```

Install with diffusion support:
```bash
pip install manifest-ml[diffusers]
```

Install with HuggingFace local model support:
```bash
pip install manifest-ml[api]
```

Dev Install:
```bash
git clone [email protected]:HazyResearch/manifest.git
cd manifest
make dev
```

# Getting Started
Running is simple to get started. If using OpenAI, set `export OPENAI_API_KEY=<OPENAIKEY>` (or pass key in through variable `client_connection`) then run

```python
from manifest import Manifest

# Start a manifest session to OpenAI - default `engine=text-davinci-003`
manifest = Manifest(
    client_name = "openai",
)
manifest.run("Why is the grass green?")
```

## Examples
We have example notebook and python scripts located at [examples](examples). These show how to use different models, model types (i.e. text, diffusers, or embedding models), and async running.

# Manifest Components
Manifest is meant to be a very light weight package to help with prompt design and iteration. Three key design decisions of Manifest are

* All models are behind APIs
* Supports caching of model inputs/outputs for iteration, reproducibility, and cost saving
* Unified API to support generate, score, and embed

## Models
Manifest provides model clients for [OpenAI](https://openai.com/), [AI21](https://studio.ai21.com/), [Cohere](https://cohere.ai/), [Together](https://together.xyz/), and HuggingFace (see [below](#huggingface-models) for how to use locally hosted HuggingFace models). You can toggle between the models by changing `client_name` and `client_connection`. For example, if a HuggingFace model is loaded locally, run
```python
manifest = Manifest(
    client_name = "huggingface",
    client_connection = "http://127.0.0.1:5000",
)
```
If you want to use Cohere, run
```python
manifest = Manifest(
    client_name = "cohere",
    client_connection = <COHERE_API_KEY>,
)
```
You can also just set `export COHERE_API_KEY=<COHERE_API_KEY>` and not use `client_connection`.

If you want to use AI21 Labs, run
```python
manifest = Manifest(
    client_name = "ai21",
    client_connection = <AI21_API_KEY>,
)
```

You can see the model details and possible model inputs to `run()` via
```python
print(manifest.client_pool.get_current_client().get_model_params())
print(manifest.client_pool.get_current_client().get_model_inputs())
```

## Global Cache
We support having queries and results stored in a global cache that can be shared across users. We treat inputs and outputs as key value pairs and support SQLite or Redis backends. To start with global caching using SQLite, run

```python
manifest = Manifest(
    client_name = "openai",
    cache_name = "sqlite",
    cache_connection = "mycache.sqlite",
)
```
The cache will be saved in `mycache.sqlite`.

We also support Redis backend.
```python
manifest = Manifest(
    client_name = "openai",
    cache_name = "redis",
    cache_connection = "localhost:6379"
)
```
As a hint, if you want to get Redis running, see the `docker run` command below under development.

## Running Queries
Once you have a session open, you can write and develop prompts.

```python
result = manifest.run("Hello, my name is Laurel")
```

You can also run over multiple examples if supported by the client.
```python
results = manifest.run(["Where are the cats?", "Where are the dogs?"])
```

We support async queries as well via
```python
import asyncio
results = asyncio.run(manifest.arun_batch(["Where are the cats?", "Where are the dogs?"]))
```

If something doesn't go right, you can also ask to get a raw manifest Response.
```python
result_object = manifest.run(["Where are the cats?", "Where are the dogs?"], return_response=True)
print(result_object.get_request_obj())
print(result_object.is_cached())
print(result_object.get_response_obj())
```

By default, we do not truncate results based on a stop token. You can change this by either passing a new stop token to a Manifest session or to a `run`.
```python
result = manifest.run(prompt, "Laurel", stop_token="and")
```

If you want to change default parameters to a model, we pass those as `kwargs` to the client.
```python
result = manifest.run(prompt, "Laurel", max_tokens=50)
```

## Streaming Queries
Manifest also supports streaming the model response back, assuming it's supported by the underlying client. When calling `run`, pass `stream=True` to get a streaming iterator in response.

```python
result_iterator = manifest.run("Tell me a story. Once upon a time", max_tokens=100, stream=True)
for res_text in result_iterator:
    print(res_text)
```
Streaming responses are only supported for single string queries (not batch mode) for text completion models.

## Model Pools
Manifest supports querying multiple models with different schedulers. This is very much a work in progress effort, but Manifest will round robin select (or randomly select) the clients you want. You can use the same client multiple times with different connection strings (e.g. different API keys), or you can mix and match. The only requirement is that all clients are the same request type. I.e. you can't have a pool of generation models and embedding models.

To query between a local model and OpenAI,
```python
from manifest.connections.client_pool import ClientConnection
from manifest import Manifest

client_connection1 = ClientConnection(
    client_name="huggingface",
    client_connection="http://127.0.0.1:5000",
)
client_connection2 = ClientConnection(client_name="openai", engine="text-ada-001")
manifest = Manifest(
    client_pool=[client_connection1, client_connection2],
    cache_name="sqlite",
    client_connection=sqlite_cache,
)
manifest.run(...)
```

The speed benefit comes in with async batched runs. When calling `arun_batch` with a list of prompts, Manifest supports a `chunk_size` param. This will break the prompts into `chunk_size` chunks to spread across the client pool. By default `chunk_size` is `-1` which means only one client will get all the prompts to run asynchronously. You must set `chunk_size > 1` to distribute across the pool. There is a further `batch_size` param which control the individual client `batch_size` to send to the model.

```python
responses = asyncio.run(manifest.arun_batch(prompts, max_tokens=30, chunk_size=20))
```

# Other Models

## Local Huggingface Models
To use a HuggingFace generative model, in `manifest/api` we have a Flask application that hosts the models for you.

In a separate terminal or Tmux/Screen session, to load 6B parameters models, run
```bash
python3 -m manifest.api.app \
    --model_type huggingface \
    --model_name_or_path EleutherAI/gpt-j-6B \
    --device 0
```
You will see the Flask session start and output a URL `http://127.0.0.1:5000`. Pass this in to Manifest. If you want to use a different port, set the `FLASK_PORT` environment variable.

```python
manifest = Manifest(
    client_name = "huggingface",
    client_connection = "http://127.0.0.1:5000",
)
```

If you have a custom model you trained, pass the model path to `--model_name_or_path`.

To help load larger models, we also support using `parallelize()` from HF, [accelerate](https://huggingface.co/docs/accelerate/index), [bitsandbytes](https://github.com/TimDettmers/bitsandbytes), and [deepspeed](https://github.com/microsoft/DeepSpeed). You will need to install these packages first via `pip install manifest-ml[api]`. We list the commands to load larger models below.

* T0pp
```bash
python3 -m manifest.api.app \
    --model_type huggingface \
    --model_name_or_path bigscience/T0pp \
    --use_hf_parallelize
```

* NeoX 20B (requires at least 60GB of GPU memory)
```bash
python3 -m manifest.api.app \
    --model_type huggingface \
    --model_name_or_path EleutherAI/gpt-neox-20b \
    --use_accelerate_multigpu \
    --percent_max_gpu_mem_reduction 0.75
```
* Bloom 175B (requires at least 240GB of GPU memory)
```bash
python3 -m manifest.api.app \
    --model_type huggingface \
    --model_name_or_path bigscience/bloom \
    --use_bitsandbytes \
    --percent_max_gpu_mem_reduction 0.85
```

## Chat Models
Manifest has specific support for executing against chat models in the more standard "system" / "user" dialogue. To pass in a dialogue history to Manifest, use the `run` command with a list of dictionary inputs with `role` and `content` keys using an associated chat model such as `openaichat`.

```python
manifest = Manifest(client_name="openaichat")
dialogue = [
    {"role": "system", "content": "You are a helpful assistant who also responds in rhymes"},
    {"role": "user", "content": "What is the date?"},
]
res = manifest.run(dialogue, max_tokens=100)
```

## Embedding Models
Manifest also supports getting embeddings from models and available APIs. We do this all through changing the `client_name` argument. You still use `run` and `abatch_run`.

To use OpenAI's embedding models, simply run
```python
manifest = Manifest(client_name="openaiembedding")
embedding_as_np = manifest.run("Get me an embedding for a bunny")
```

As explained above, you can load local HuggingFace models that give you embeddings, too. If you want to use a standard generative model, load the model as above use use `client_name="huggingfaceembedding"`. If you want to use a standard embedding model, like those from SentenceTransformers, load your local model via
```bash
python3 -m manifest.api.app \
    --model_type sentence_transformers \
    --model_name_or_path all-mpnet-base-v2 \
    --device 0
```

# Road Map
Here's what's coming up next
- [ ] Clients
  - [ ] HuggingFace Hub
  - [x] Azure OpenAI
  - [x] Google Vertex
  - [ ] Anthropic
  - [x] Streaming Support Completions
  - [ ] Streaming Support Chat Models
- [ ] Data Types
  - [ ] Diffusion Models
- [x] Orchestration
  - [x] Connection pools
- [ ] Local Inference
  - [ ] FlexGen

# Development
Before submitting a PR, run
```bash
export REDIS_PORT="6379"  # or whatever PORT local redis is running for those tests
cd <REDIS_PATH>
docker run -d -p 127.0.0.1:${REDIS_PORT}:6379 -v `pwd`:`pwd` -w `pwd` --name manifest_redis_test redis
make test
```

# Cite
Please cite Manifest if you used it for any publications. Thanks!!
```
@misc{orr2022manifest,
  author = {Orr, Laurel},
  title = {Manifest},
  year = {2022},
  publisher = {GitHub},
  howpublished = {\url{https://github.com/HazyResearch/manifest}},
}
```