从 langchain runnable 返回 FastAPI HTTPException 到前端

问题描述 投票:0回答:2

我的后端正在运行具有某些可运行项的 langchain 路由。我希望能够向前端返回“404 Not found”之类的 http 异常,但是当我使用

raise HTTPException(status_code=404, detail="Item not found")
引发它时,会创建 CancelledException 并且前端收到“内部服务器错误”。我怎样才能做到这一点?

ERROR:    Exception in ASGI application
Traceback (most recent call last):
  File "/my-code-path/.venv/lib/python3.10/site-packages/sse_starlette/sse.py", line 269, in __call__
    await wrap(partial(self.listen_for_disconnect, receive))
  File "/my-code-path/.venv/lib/python3.10/site-packages/sse_starlette/sse.py", line 258, in wrap
    await func()
  File "/my-code-path/.venv/lib/python3.10/site-packages/sse_starlette/sse.py", line 215, in listen_for_disconnect
    message = await receive()
  File "/my-code-path/.venv/lib/python3.10/site-packages/uvicorn/protocols/http/httptools_impl.py", line 596, in receive
    await self.message_event.wait()
  File "/usr/lib/python3.10/asyncio/locks.py", line 214, in wait
    await fut
asyncio.exceptions.CancelledError: Cancelled by cancel scope 7fba499a8490

During handling of the above exception, another exception occurred:

  + Exception Group Traceback (most recent call last):
  |   File "/my-code-path/.venv/lib/python3.10/site-packages/uvicorn/protocols/http/httptools_impl.py", line 435, in run_asgi
  |     result = await app(  # type: ignore[func-returns-value]
  |   File "/my-code-path/.venv/lib/python3.10/site-packages/uvicorn/middleware/proxy_headers.py", line 78, in __call__
  |     return await self.app(scope, receive, send)
  |   File "/my-code-path/.venv/lib/python3.10/site-packages/fastapi/applications.py", line 276, in __call__
  |     await super().__call__(scope, receive, send)
  |   File "/my-code-path/.venv/lib/python3.10/site-packages/starlette/applications.py", line 122, in __call__
  |     await self.middleware_stack(scope, receive, send)
  |   File "/my-code-path/.venv/lib/python3.10/site-packages/starlette/middleware/errors.py", line 184, in __call__
  |     raise exc
  |   File "/my-code-path/.venv/lib/python3.10/site-packages/starlette/middleware/errors.py", line 162, in __call__
  |     await self.app(scope, receive, _send)
  |   File "/my-code-path/.venv/lib/python3.10/site-packages/starlette/middleware/cors.py", line 91, in __call__
  |     await self.simple_response(scope, receive, send, request_headers=headers)
  |   File "/my-code-path/.venv/lib/python3.10/site-packages/starlette/middleware/cors.py", line 146, in simple_response
  |     await self.app(scope, receive, send)
  |   File "/my-code-path/.venv/lib/python3.10/site-packages/starlette/middleware/exceptions.py", line 79, in __call__
  |     raise exc
  |   File "/my-code-path/.venv/lib/python3.10/site-packages/starlette/middleware/exceptions.py", line 68, in __call__
  |     await self.app(scope, receive, sender)
  |   File "/my-code-path/.venv/lib/python3.10/site-packages/fastapi/middleware/asyncexitstack.py", line 21, in __call__
  |     raise e
  |   File "/my-code-path/.venv/lib/python3.10/site-packages/fastapi/middleware/asyncexitstack.py", line 18, in __call__
  |     await self.app(scope, receive, send)
  |   File "/my-code-path/.venv/lib/python3.10/site-packages/starlette/routing.py", line 718, in __call__
  |     await route.handle(scope, receive, send)
  |   File "/my-code-path/.venv/lib/python3.10/site-packages/starlette/routing.py", line 276, in handle
  |     await self.app(scope, receive, send)
  |   File "/my-code-path/.venv/lib/python3.10/site-packages/starlette/routing.py", line 69, in app
  |     await response(scope, receive, send)
  |   File "/my-code-path/.venv/lib/python3.10/site-packages/sse_starlette/sse.py", line 255, in __call__
  |     async with anyio.create_task_group() as task_group:
  |   File "/my-code-path/.venv/lib/python3.10/site-packages/anyio/_backends/_asyncio.py", line 680, in __aexit__
  |     raise BaseExceptionGroup(
  | exceptiongroup.ExceptionGroup: unhandled errors in a TaskGroup (1 sub-exception)
  +-+---------------- 1 ----------------
    | Traceback (most recent call last):
    |   File "/my-code-path/.venv/lib/python3.10/site-packages/sse_starlette/sse.py", line 258, in wrap
    |     await func()
    |   File "/my-code-path/.venv/lib/python3.10/site-packages/sse_starlette/sse.py", line 245, in stream_response
    |     async for data in self.body_iterator:
    |   File "/my-code-path/.venv/lib/python3.10/site-packages/langserve/api_handler.py", line 1121, in _stream
    |     async for chunk in self._runnable.astream(
    |   File "/my-code-path/.venv/lib/python3.10/site-packages/langchain_core/runnables/base.py", line 4745, in astream
    |     async for item in self.bound.astream(
    |   File "/my-code-path/.venv/lib/python3.10/site-packages/langchain_core/runnables/base.py", line 2898, in astream
    |     async for chunk in self.atransform(input_aiter(), config, **kwargs):
    |   File "/my-code-path/.venv/lib/python3.10/site-packages/langchain_core/runnables/base.py", line 2881, in atransform
    |     async for chunk in self._atransform_stream_with_config(
    |   File "/my-code-path/.venv/lib/python3.10/site-packages/langchain_core/runnables/base.py", line 1972, in _atransform_stream_with_config
    |     chunk = cast(Output, await py_anext(iterator))
    |   File "/my-code-path/.venv/lib/python3.10/site-packages/langchain_core/runnables/base.py", line 2851, in _atransform
    |     async for output in final_pipeline:
    |   File "/my-code-path/.venv/lib/python3.10/site-packages/langchain_core/runnables/base.py", line 4178, in atransform
    |     async for output in self._atransform_stream_with_config(
    |   File "/my-code-path/.venv/lib/python3.10/site-packages/langchain_core/runnables/base.py", line 1972, in _atransform_stream_with_config
    |     chunk = cast(Output, await py_anext(iterator))
    |   File "/my-code-path/.venv/lib/python3.10/site-packages/langchain_core/runnables/base.py", line 4147, in _atransform
    |     output = await acall_func_with_variable_args(
    |   File "/my-code-path/.venv/lib/python3.10/site-packages/langchain_core/runnables/base.py", line 4122, in f
    |     return await run_in_executor(config, func, *args, **kwargs)
    |   File "/my-code-path/.venv/lib/python3.10/site-packages/langchain_core/runnables/config.py", line 547, in run_in_executor
    |     return await asyncio.get_running_loop().run_in_executor(
    |   File "/usr/lib/python3.10/concurrent/futures/thread.py", line 58, in run
    |     result = self.fn(*self.args, **self.kwargs)
    |   File "/my-code-path/.venv/lib/python3.10/site-packages/langchain_core/runnables/base.py", line 4116, in func
    |     return call_func_with_variable_args(
    |   File "/my-code-path/.venv/lib/python3.10/site-packages/langchain_core/runnables/config.py", line 380, in call_func_with_variable_args
    |     return func(input, **kwargs)  # type: ignore[call-arg]
    |   File "/my-code-path/src/chains/forms/refine_chain.py", line 65, in get_refined_runnable_map
    |     raise HTTPException(status_code=404, detail="Item not found")
    | fastapi.exceptions.HTTPException
    +------------------------------------

我尝试寻找一种方法以某种方式捕获该异常,但可运行对象直接插入到“add_routes”函数中,因此我不知道如何执行此操作,因为可运行对象内的任何异常都会引发“CancelledException”。

refine_chain = RefineChain(custom_app, tool_name)
add_routes(
  app,
  refine_chain.get_runnable().with_config({"tags": [custom_app]}),
  enabled_endpoints=["stream"],
  path=f"/{custom_app}/{tool_name}/refine",
  config_keys=["configurable"],
  dependencies=[Depends(get_current_active_username)],
)   
python backend fastapi langchain py-langchain
2个回答
0
投票

我通常通过

exception_handler
-s 来管理异常,因此当项目增长时它可以扩展得更多,以下是我将如何实现处理代码引发的
asyncio.exceptions.CancelledError

@app.exception_handler(asyncio.exceptions.CancelledError)
    async def http_exception_handler(req: Request, exc: RequestValidationError) -> Response:
        error_message = 'Bad Request'
        return JSONResponse(
            status_code=400,
            content={"message": error_message},
        )

注:

app
app = FastAPI(...)

您可以根据自己的喜好自定义

JSONResponse
,添加
404
以及您想要的任何消息。


0
投票

LangServe 的当前实现对流方法有硬编码的错误处理:

https://github.com/langchain-ai/langserve/blob/v0.3.0/langserve/api_handler.py#L1210-L1219

LangServe 存储库中有一个未解决的问题来解决此限制: https://github.com/langchain-ai/langserve/issues/481

因此,客户端将始终收到相同的“内部服务器错误”消息。

© www.soinside.com 2019 - 2024. All rights reserved.