模式验证错误FastAPI和pydantic

2024-05-17 07:00:34 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在使用FastAPI框架创建一个API,我的post请求负载如下所示

{
    "batch_id": "7r3683693242",
    "queries": [
        "What is the capital of Germany",
        "How is Electricity generated"
    ],
    "num_items_to_return": 2,
    "passage_id_and_score_matrix": [
        [
            ["16278720_0", 0.8], ["169339_0", 0.6]
        ],
        [
            ["19258753_14", 0.6], ["3270043_12", 0.4]
        ]
    ]
 }

我将我的pydantic模型定义为

class ReRankerPayload(BaseModel):
    batch_id: str
    queries: List[str]
    num_items_to_return: int
    passage_id_and_score_matrix: List[List[Tuple[str, float]]]

还有我的API签名

@app.post("/rerank-passages")
async def rerank_passages(payload: ReRankerPayload):
    response = reranker.get_results(
        payload.batch_id, payload.queries,                                    
        payload.passage_id_and_score_matrix, 
        payload.num_items_to_return,
    )
    return response

uvicorn.run(app, host="0.0.0.0", port=8080, log_config=None)

当我打开位于127.0.0.1:8080/docs上的招摇过市页面时,我得到了以下错误

  File "/home/dimension/.virtualenvs/buddy/lib/python3.8/site-packages/starlette/middleware/errors.py", line 159, in __call__
    await self.app(scope, receive, _send)
  File "/home/dimension/.virtualenvs/buddy/lib/python3.8/site-packages/starlette/exceptions.py", line 82, in __call__
    raise exc
  File "/home/dimension/.virtualenvs/buddy/lib/python3.8/site-packages/starlette/exceptions.py", line 71, in __call__
    await self.app(scope, receive, sender)
  File "/home/dimension/.virtualenvs/buddy/lib/python3.8/site-packages/starlette/routing.py", line 656, in __call__
    await route.handle(scope, receive, send)
  File "/home/dimension/.virtualenvs/buddy/lib/python3.8/site-packages/starlette/routing.py", line 259, in handle
    await self.app(scope, receive, send)
  File "/home/dimension/.virtualenvs/buddy/lib/python3.8/site-packages/starlette/routing.py", line 61, in app
    response = await func(request)
  File "/home/dimension/.virtualenvs/buddy/lib/python3.8/site-packages/fastapi/applications.py", line 161, in openapi
    return JSONResponse(self.openapi())
  File "/home/dimension/.virtualenvs/buddy/lib/python3.8/site-packages/fastapi/applications.py", line 136, in openapi
    self.openapi_schema = get_openapi(
  File "/home/dimension/.virtualenvs/buddy/lib/python3.8/site-packages/fastapi/openapi/utils.py", line 410, in get_openapi
    return jsonable_encoder(OpenAPI(**output), by_alias=True, exclude_none=True)  # type: ignore
  File "pydantic/main.py", line 362, in pydantic.main.BaseModel.__init__
pydantic.error_wrappers.ValidationError: 2 validation errors for OpenAPI
components -> schemas -> ReRankerPayload -> properties -> passage_id_and_score_matrix -> items -> items -> items
  value is not a valid dict (type=type_error.dict)
components -> schemas -> ReRankerPayload -> $ref
  field required (type=value_error.missing)

上述代码在fastapi版本0.65.2上运行良好,但在0.70.0上运行不好。无论fastapi版本如何,如何使上述代码正常工作


Tags: inpyidhomereturnlibpackagesline
1条回答
网友
1楼 · 发布于 2024-05-17 07:00:34

看起来元组当前是not supported in OpenAPI

有两种方法可以解决这个问题:

  1. ListUnion一起使用:
from pydantic import BaseModel
from typing import List, Union

class ReRankerPayload(BaseModel):
    batch_id: str
    queries: List[str]
    num_items_to_return: int
    passage_id_and_score_matrix: List[List[List[Union[str, float]]]]

这是最快的解决方案,但无法确保最内层列表/数组中的项数。 enter image description here

  1. 正如链接线程中所建议的,您可以使用Pydantic的^{}
from pydantic import BaseModel, conlist
from typing import List, Union

class ReRankerPayload(BaseModel):
    batch_id: str
    queries: List[str]
    num_items_to_return: int
    passage_id_and_score_matrix: List[List[conlist(Union[str, float], min_items=2, max_items=2)]]

这将确保在最里面的列表中只能传递两个项目,并且它们要么是str要么是float,但是,它不能确保顺序。 enter image description here

    如果你能适应请求体,考虑把它改为:
from pydantic import BaseModel
from typing import List

class Entry(BaseModel):
    id: str
    score: float

class ReRankerPayload(BaseModel):
    batch_id: str
    queries: List[str]
    num_items_to_return: int
    passage_id_and_score_matrix: List[List[Entry]]

这提高了可读性,并确保Entry始终恰好具有两个属性(idscore)。 enter image description here

相关问题 更多 >