diff --git a/app/controller/add_docs_route.py b/app/controller/add_docs_route.py new file mode 100644 index 0000000..e4af861 --- /dev/null +++ b/app/controller/add_docs_route.py @@ -0,0 +1,63 @@ +from fastapi import FastAPI +from fastapi.openapi.docs import get_swagger_ui_oauth2_redirect_html, get_redoc_html, get_swagger_ui_html +from fastapi.responses import RedirectResponse +from starlette.staticfiles import StaticFiles + + +def add_docs_route(app: FastAPI): + """ + 专门处理文档静态资源本地代理的接口 + """ + + app.mount("/static", StaticFiles(directory="static"), name="static") + + # 自定义 Swagger 页面(使用本地资源) + @app.get("/docs", include_in_schema=False) + async def custom_swagger_ui(): + """ + 提供自定义的 Swagger UI 文档页面 + + Returns: + Swagger UI HTML 页面,使用本地静态资源加载 + """ + return get_swagger_ui_html( + openapi_url=app.openapi_url, + title=app.title + " - Swagger UI", + oauth2_redirect_url=app.swagger_ui_oauth2_redirect_url, + swagger_js_url="/static/swagger-ui-bundle.min.js", + swagger_css_url="/static/swagger-ui.min.css", + ) + + @app.get(app.swagger_ui_oauth2_redirect_url, include_in_schema=False) + async def swagger_ui_redirect(): + """ + 处理 Swagger UI 的 OAuth2 重定向回调 + + Returns: + OAuth2 重定向 HTML 响应 + """ + return get_swagger_ui_oauth2_redirect_html() + + @app.get("/redoc", include_in_schema=False) + async def redoc_html(): + """ + 提供自定义的 ReDoc 文档页面 + + Returns: + ReDoc HTML 页面,使用本地静态资源加载 + """ + return get_redoc_html( + openapi_url=app.openapi_url, + title=app.title + " - ReDoc", + redoc_js_url="/static/redoc.standalone.js", + ) + + @app.get("/") + async def redirect_root_to_docs(): + """ + 将根路径请求重定向到 Swagger 文档页面 + + Returns: + 重定向响应到 /docs 路径 + """ + return RedirectResponse("/docs") diff --git a/app/controller/add_test_route.py b/app/controller/add_test_route.py new file mode 100644 index 0000000..b728364 --- /dev/null +++ b/app/controller/add_test_route.py @@ -0,0 +1,36 @@ +from fastapi import FastAPI +from langchain.chat_models import init_chat_model +from langserve import add_routes + +from app.utils.llm_utils import create_llm + + +def add_test_route(app: FastAPI): + @app.get("/chat") + async def chat(): + model_qwen = create_llm(platform_code='bailian-qwen-turbo') + model_qwen_output = model_qwen.invoke("你好,你是谁").content + print(f"model_qwen output: {model_qwen_output}") + + model_doubao = create_llm(platform_code='huoshan-doubao') + model_doubao_output = model_doubao.invoke("你好,你是谁").content + print(f"model_doubao output: {model_doubao_output}") + + return { + "model_qwen_output": model_qwen_output, + "model_doubao_output": model_doubao_output + } + + # Edit this to add the chain you want to add + # add_routes(app, NotImplemented) + + model = init_chat_model( + model="doubao-1-5-pro-32k-250115", # 你的模型名 + model_provider="openai", # 必须填 openai(兼容协议) + base_url="https://ark.cn-beijing.volces.com/api/v3/", # 你的自定义 API URL + api_key="b1e7c7e0-33af-480e-b0a8-2812ba97f7b1", # 本地模型随便填 + temperature=0.7, + streaming=False + ) + + add_routes(app=app, runnable=model, path="/doubao") diff --git a/app/main.py b/app/main.py new file mode 100644 index 0000000..d21665d --- /dev/null +++ b/app/main.py @@ -0,0 +1,35 @@ +import datetime +from contextlib import asynccontextmanager + +from fastapi import FastAPI +from fastapi.openapi.docs import get_swagger_ui_oauth2_redirect_html, get_redoc_html, get_swagger_ui_html +from fastapi.responses import RedirectResponse +from langchain.chat_models import init_chat_model +from langserve import add_routes +from starlette.staticfiles import StaticFiles + +from app.config.env import env +from app.controller.add_custom_stream_route import add_custom_stream_route +from app.controller.add_graph_proxy_route import add_graph_proxy_route +from app.routes import routes +from app.utils.get_local_ips import get_local_ips +from app.utils.llm_utils import create_llm + + +@asynccontextmanager +async def lifespan(app: FastAPI): + print(f"应用启动:{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}") + yield + print(f"应用销毁:{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}") + + +app = FastAPI( + lifespan=lifespan, + docs_url=None, # 禁用默认 Swagger + redoc_url=None, # 禁用默认 ReDoc +) + +for add_route_func in routes: + add_route_func(app) + +print("/*---------------------------------------main-------------------------------------------*/") diff --git a/app/routes.py b/app/routes.py new file mode 100644 index 0000000..c6d9436 --- /dev/null +++ b/app/routes.py @@ -0,0 +1,13 @@ +from app.controller.add_custom_stream_route import add_custom_stream_route +from app.controller.add_docs_route import add_docs_route +from app.controller.add_graph_proxy_route import add_graph_proxy_route +from app.controller.add_test_route import add_test_route + +# /*@formatter:off*/ +routes = [ + add_docs_route, # 代理文档静态资源 + add_test_route, # 测试接口 + add_graph_proxy_route, # 代理自定义工作流 + add_custom_stream_route, # 自定义流式接口 +] +# /*@formatter:on*/ diff --git a/main.py b/main.py index a6498a0..e47c5ac 100644 --- a/main.py +++ b/main.py @@ -1,122 +1,5 @@ -import datetime -from contextlib import asynccontextmanager - -from fastapi import FastAPI -from fastapi.openapi.docs import get_swagger_ui_oauth2_redirect_html, get_redoc_html, get_swagger_ui_html -from fastapi.responses import RedirectResponse -from langchain.chat_models import init_chat_model -from langserve import add_routes -from starlette.staticfiles import StaticFiles - from app.config.env import env -from app.controller.add_custom_stream_route import add_custom_stream_route -from app.controller.add_graph_proxy_route import add_graph_proxy_route from app.utils.get_local_ips import get_local_ips -from app.utils.llm_utils import create_llm - - -@asynccontextmanager -async def lifespan(app: FastAPI): - print(f"应用启动:{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}") - yield - print(f"应用销毁:{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}") - - -app = FastAPI( - lifespan=lifespan, - docs_url=None, # 禁用默认 Swagger - redoc_url=None, # 禁用默认 ReDoc -) -app.mount("/static", StaticFiles(directory="static"), name="static") - - -# 自定义 Swagger 页面(使用本地资源) -@app.get("/docs", include_in_schema=False) -async def custom_swagger_ui(): - """ - 提供自定义的 Swagger UI 文档页面 - - Returns: - Swagger UI HTML 页面,使用本地静态资源加载 - """ - return get_swagger_ui_html( - openapi_url=app.openapi_url, - title=app.title + " - Swagger UI", - oauth2_redirect_url=app.swagger_ui_oauth2_redirect_url, - swagger_js_url="/static/swagger-ui-bundle.min.js", - swagger_css_url="/static/swagger-ui.min.css", - ) - - -@app.get(app.swagger_ui_oauth2_redirect_url, include_in_schema=False) -async def swagger_ui_redirect(): - """ - 处理 Swagger UI 的 OAuth2 重定向回调 - - Returns: - OAuth2 重定向 HTML 响应 - """ - return get_swagger_ui_oauth2_redirect_html() - - -@app.get("/redoc", include_in_schema=False) -async def redoc_html(): - """ - 提供自定义的 ReDoc 文档页面 - - Returns: - ReDoc HTML 页面,使用本地静态资源加载 - """ - return get_redoc_html( - openapi_url=app.openapi_url, - title=app.title + " - ReDoc", - redoc_js_url="/static/redoc.standalone.js", - ) - - -@app.get("/") -async def redirect_root_to_docs(): - """ - 将根路径请求重定向到 Swagger 文档页面 - - Returns: - 重定向响应到 /docs 路径 - """ - return RedirectResponse("/docs") - - -@app.get("/chat") -async def chat(): - model_qwen = create_llm(platform_code='bailian-qwen-turbo') - model_qwen_output = model_qwen.invoke("你好,你是谁").content - print(f"model_qwen output: {model_qwen_output}") - - model_doubao = create_llm(platform_code='huoshan-doubao') - model_doubao_output = model_doubao.invoke("你好,你是谁").content - print(f"model_doubao output: {model_doubao_output}") - - return { - "model_qwen_output": model_qwen_output, - "model_doubao_output": model_doubao_output - } - - -# Edit this to add the chain you want to add -# add_routes(app, NotImplemented) - -model = init_chat_model( - model="doubao-1-5-pro-32k-250115", # 你的模型名 - model_provider="openai", # 必须填 openai(兼容协议) - base_url="https://ark.cn-beijing.volces.com/api/v3/", # 你的自定义 API URL - api_key="b1e7c7e0-33af-480e-b0a8-2812ba97f7b1", # 本地模型随便填 - temperature=0.7, - streaming=False -) - -add_routes(app=app, runnable=model, path="/doubao") - -add_graph_proxy_route(app) -add_custom_stream_route(app) if __name__ == "__main__": import uvicorn @@ -139,7 +22,7 @@ uvicorn.run() 启动了一个异步事件循环来处理 HTTP 请求, 因此,uvicorn.run() 之后的代码不会被执行,直到服务器关闭。 """ # 启动Uvicorn服务器 - uvicorn.run("main:app", host="0.0.0.0", port=port) + uvicorn.run("app.main:app", host="0.0.0.0", port=port) # uvicorn.run之后的代码永远都不会执行 # 使用FastAPI的 @app.on_event("startup")装饰器可以在服务器成功启动后执行代码