python - 发布请求 tensorflow 服务:解包的值太多(预期 2)
问题描述
我使用我的模型设置了一个 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)
这是我的代码:
res, res2 = requests.post('http://url:port/v1/models/colbert:predict',
data=sentence_input)
print(res.status_code, res.reason)
我的 data_sentence 是一个数组数组:
[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]
解决方案
您的代码中有两个单独的问题。一个与有效负载有关,另一个与您使用的方式有关requests.post
。
请求使用
requests.post
,就像requests.request
和其他类似的函数一样,返回类的单个实例Response
(source)。因此,要修复您的错误,您需要从
res, res2 = requests.post(...
至
res = requests.post(
现在,通常如果你尝试将一个东西解压成两个变量,你会得到一个更清晰的错误,指出没有足够的值可以解压:
>>> a,b = [1]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: not enough values to unpack (expected 2, got 1)
你得到的错误实际上是相反的——你有太多的值需要解压。这就是为什么。
Response
由返回的类requests.post
定义了一个__iter__(self)
方法(source),这将允许您以块的形式迭代响应,而不是一次读取所有响应。因此,当您这样做时res, res2 = response
,Python 将尝试使用__iter__
实现为您解包响应。如果您的响应中有超过 2 个块,您将没有足够的变量来处理其他块,因此您会收到错误“太多值无法解包”。
这种行为的简单演示:
>>> 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]
有效载荷
当您将data
关键字参数传递给 时requests.post
,它假定您要对其进行形式编码(docs)。您应该传递字典或元组列表,但是您拥有的是数组列表,它根本不是表单,因此您不想对其进行形式编码。
因此,当您传递 时(data=list_of_arrays)
,库期望第一个元素是具有两个元素的元组。相反,您有一个包含更多元素的数组,这再次导致相同的错误:unpack 的值太多。
您想要做的是将其作为 JSON 或仅作为字符串发送。通常,您必须遵循文档并执行
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
不幸的是,您将遇到np.array
不可序列化的问题,因此您必须先为序列化做好准备。根据这个答案,您只需调用.tolist()
它将np.array
为您将其序列化为整数列表。
因此最终的解决方案
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
推荐阅读
- wpf - VB WPF xaml 文件引用 My.Resources
- laravel-5 - 如何在 cpanel 中启用工匠命令?
- php - 如果它在单个帖子内容中,如何链接到类别标题?
- python - 在我的目录结构中,我想在我的测试文件中使用 api_libs。有人可以帮助我正确的导入方式吗?
- database - 如何在网络徽标中记录乌龟访问的补丁的位置,并为每个乌龟重新排列数据
- cron - 如何避免两个预定作业的冲突
- r - 如何在R中一次性进行汇总统计
- postgresql - PostgreSQL 12 docker 容器无法在特定架构上重新启动
- javascript - How to use Puppeteer on NODE server and get the results on frontend HTML page?
- python - 使用 pandas crosstab 和 pandas_ml ConfusionMatrix 创建混淆矩阵的问题