import datetime import logging from contextlib import asynccontextmanager from typing import List, Union 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 langchain_core.messages import HumanMessage, AIMessage, SystemMessage from langchain_core.prompts import ChatPromptTemplate from langchain_core.runnables import RunnableGenerator from langchain_openai import ChatOpenAI from langserve import add_routes from pydantic import BaseModel, Field from starlette.staticfiles import StaticFiles from app.config.env import env from app.controller.add_test_route import add_test_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="/qwen") add_test_route(app) if __name__ == "__main__": import uvicorn # 获取环境变量中的端口号 port = int(env.server_port) # 打印所有可用的访问地址 print("\n服务已启动,以下是可用的访问地址:") print(f" - 本地访问: http://127.0.0.1:{port}") for ip in get_local_ips(): print(f" - 网络访问: http://{ip}:{port}") print("\n") # 空行美化输出 """ uvicorn.run() 启动了一个异步事件循环来处理 HTTP 请求, 这个循环会一直运行直到服务器被手动停止(比如按下 Ctrl+C)。 因此,uvicorn.run() 之后的代码不会被执行,直到服务器关闭。 """ # 启动Uvicorn服务器 uvicorn.run("main:app", host="0.0.0.0", port=port) # uvicorn.run之后的代码永远都不会执行 # 使用FastAPI的 @app.on_event("startup")装饰器可以在服务器成功启动后执行代码 print('App is running...(Never Callable)')