[英]Post request tensorflow serving: too many values to unpack (expected 2)
I set up a tensorflow running service with my model, but when I try to do a post request it returns me the following error (get request work):我用我的 model 设置了一个 tensorflow 运行服务,但是当我尝试进行发布请求时,它返回了以下错误(获取请求工作):
[nltk_data] Downloading package punkt to /home/viktor/nltk_data...
[nltk_data] Package punkt is already up-to-date!
HBox(children=(FloatProgress(value=1.0, bar_style='info', max=1.0), HTML(value='')))
Truncation was not explicitly activated but `max_length` is provided a specific value, please use `truncation=True` to explicitly truncate examples to max length. Defaulting to 'longest_first' truncation strategy. If you encode pairs of sequences (GLUE-style) with the tokenizer you can select this strategy more precisely by providing a specific strategy to `truncation`.
(3, 20)
Traceback (most recent call last):
File "bert_api.py", line 99, in <module>
res , res2= requests.post('http://3.143.108.46:8501/v1/models/colbert:predict',
File "/home/viktor/documents/miniconda3/lib/python3.8/site-packages/requests/api.py", line 119, in post
return request('post', url, data=data, json=json, **kwargs)
File "/home/viktor/documents/miniconda3/lib/python3.8/site-packages/requests/api.py", line 61, in request
return session.request(method=method, url=url, **kwargs)
File "/home/viktor/documents/miniconda3/lib/python3.8/site-packages/requests/sessions.py", line 516, in request
prep = self.prepare_request(req)
File "/home/viktor/documents/miniconda3/lib/python3.8/site-packages/requests/sessions.py", line 449, in prepare_request
p.prepare(
File "/home/viktor/documents/miniconda3/lib/python3.8/site-packages/requests/models.py", line 317, in prepare
self.prepare_body(data, files, json)
File "/home/viktor/documents/miniconda3/lib/python3.8/site-packages/requests/models.py", line 508, in prepare_body
body = self._encode_params(data)
File "/home/viktor/documents/miniconda3/lib/python3.8/site-packages/requests/models.py", line 97, in _encode_params
for k, vs in to_key_val_list(data):
ValueError: too many values to unpack (expected 2)
This is my code:这是我的代码:
res, res2 = requests.post('http://url:port/v1/models/colbert:predict',
data=sentence_input)
print(res.status_code, res.reason)
my data_sentence is an array of arrays:我的 data_sentence 是一个 arrays 数组:
[array([[1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]],
dtype=int32),
array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=int32]
There are two separate issues in your code.您的代码中有两个单独的问题。 One pertains to the payload, the other to the way you are using
requests.post
.一个与有效负载有关,另一个与您使用
requests.post
的方式有关。
requests.post
, just as requests.request
and other similar functions, returns a single instance of Response
class ( source ). requests.post
与requests.request
和其他类似函数一样,返回单个Response
class 实例( 来源)。 For this reason, to fix your error you need to change from因此,要修复您的错误,您需要从
res, res2 = requests.post(...
to至
res = requests.post(
Now, typically if you try to take one thing and unpack it into two variables, you would get a more clear error saying that there are not enough values to unpack:现在,通常如果你尝试将一个东西解压成两个变量,你会得到一个更清晰的错误,指出没有足够的值可以解压:
>>> a,b = [1]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: not enough values to unpack (expected 2, got 1)
The error you are getting actually says the opposite - that you have too many values to unpack.你得到的错误实际上是相反的——你有太多的值需要解压。 And here's why.
这就是为什么。
The Response
class returned by requests.post
defines an __iter__(self)
method ( source ), which will allow you to iterate over the response in chunks instead of reading it all at once. requests.post
返回的Response
class 定义了一个__iter__(self)
方法( source ),这将允许您以块的形式迭代响应,而不是一次读取所有响应。 So when you do res, res2 = response
, Python will try to unpack the response for you by using the __iter__
implementation.因此,当您执行
res, res2 = response
时,Python 将尝试使用__iter__
实现为您解压响应。 If you have more than 2 chunks in your response, you won't have enough variables to handle the other chunks, so you get the error "too many values to unpack".如果您的响应中有超过 2 个块,您将没有足够的变量来处理其他块,因此您会收到错误“太多值无法解包”。
A simple demonstration of this behaviour:这种行为的简单演示:
>>> class X():
... def __iter__(self):
... for i in range(5):
... yield i
...
>>> x = X()
>>> a,b = x
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: too many values to unpack (expected 2)
>>> list(x)
[0, 1, 2, 3, 4]
When you pass in the data
keyword argument to requests.post
, it assumes that you want to form-encode it ( docs ).当您将
data
关键字参数传递给requests.post
时,它假定您想要对其进行形式编码( docs )。 You should either pass a dictionary or a list of tuples, but what you have is a list of arrays, which isn't a form at all, so you don't want to form-encode it.您应该传递字典或元组列表,但您拥有的是 arrays 列表,它根本不是表单,因此您不想对其进行形式编码。
So when you are passing (data=list_of_arrays)
, the library expects the first element to be a tuple with two elements.因此,当您传递
(data=list_of_arrays)
时,库期望第一个元素是具有两个元素的元组。 Instead you have an array with much more elements, which again results in the same error: too many values to unpack .相反,您有一个包含更多元素的数组,这再次导致相同的错误: unpack 的值太多。
What you want to do instead is to send it as JSON or just as a string.您要做的是将其作为 JSON 或仅作为字符串发送。 Typically, you would have to follow the docs and do
通常,您必须遵循文档并执行
import json
payload = [np.random.randint(2, size=30).reshape(3,10), np.random.randint(2, size=30).reshape(3,10)]
res = requests.post('/', data=json.dumps(payload)) # pass it as a string
res = requests.post('/', json=payload) # or let the library serialize it
Unfortunately, you will then run into the issue where np.array
isn't serializable, so you have to prepare it for serialization first.不幸的是,您将遇到
np.array
不可序列化的问题,因此您必须先为序列化做好准备。 As per this answer , you can just call .tolist()
on np.array
which will serialize it to a list of integers for you.根据这个答案,您可以在
np.array
上调用.tolist()
,它将为您将其序列化为整数列表。
Thus the final solution因此最终的解决方案
import json
payload = [np.random.randint(2, size=30).reshape(3,10), np.random.randint(2, size=30).reshape(3,10)]
# convert both np.arrays to list
payload = [payload[0].tolist(), payload[1].tolist()]
# or this way
payload = [arr.tolist() for arr in data]
# now the payload is serializable
res = requests.post('/', data=json.dumps(payload)) # pass it as a string
res = requests.post('/', json=payload) # or let the library serialize it
Looking at the error message i see that you are assigning two variables res, res2 to requests.post response that has more than 2 returning values查看错误消息,我看到您正在将两个变量 res、res2 分配给具有超过 2 个返回值的 requests.post 响应
#for example
var1, var2 = [1, 2, 3]
#this will raise the same error as your's
To solve this problem you need to index your response like this below要解决此问题,您需要像下面这样索引您的响应
res, res2 = requests.post('http://url:port/v1/models/colbert:predict',
data=sentence_input)[:2]
print(res.status_code, res.reason)
If response to your post request return a list, indexing will solve your problem如果对您的帖子请求的响应返回一个列表,索引将解决您的问题
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.