返回顶部
热门问答 更多热门问答
技术文章 更多技术文章

结合fastapi-users与Langserve轻松实现大语言接口用户认证

[复制链接]
链载Ai 显示全部楼层 发表于 1 小时前 |阅读模式 打印 上一主题 下一主题

在做大模型开发的过程中,相信很多小伙伴都是对大模型开发感兴趣,却对 fastapi 这个框架并不熟悉,但是,实际开发的项目确需要用户鉴权,这时候就会很头疼,查阅官方文档发现,官方虽然有例子,但是写的非常简单,只有一个自定义的verify_token函数,函数内容还需要自己实现,如果投入学习成本在 fastapi 的用户认证上就显得得不偿失。而 fastapi 是有现成的用户认证的框架的,比如 fastapi-users。今天,我就带领大家完成一个使用 fastapi-users来实现带有用户认证功能的Langserve接口。

以上是官方的认证鉴权的方法,实现过程需要自己来完成。

实现步骤:

下载fastapi-users

pipinstall'fastapi-users[sqlalchemy]'

代码目录结构

创建 langserve 项目的方法我就不再介绍了,感兴趣的同学,可以看我的这篇公众号文章:LangServe全面使用指南

.
├──app
│├──db.py
│├──__init__.py
│├──__pycache__
│├──schemas.py
│├──server.py
│└──users.py
├──Dockerfile
├──packages
│└──README.md
├──poetry.lock
├──pyproject.toml
├──README.md
└──test.db

其中,db.py、users.py、schemas.py都是新建的 python 文件,这个目录结构也是fastapi-users推荐的拆分方式。

代码编写

db.py

fromtypingimportAsyncGenerator

fromfastapiimportDepends
fromfastapi_users.dbimportSQLAlchemyBaseUserTableUUID,SQLAlchemyUserDatabase
fromsqlalchemy.ext.asyncioimportAsyncSession,async_sessionmaker,create_async_engine
fromsqlalchemy.ormimportDeclarativeBase

DATABASE_URL="sqlite+aiosqlite:///./test.db"


classBase(DeclarativeBase):
pass


classUser(SQLAlchemyBaseUserTableUUID,Base):
pass


engine=create_async_engine(DATABASE_URL)
async_session_maker=async_sessionmaker(engine,expire_on_commit=False)


asyncdefcreate_db_and_tables():
asyncwithengine.begin()asconn:
awaitconn.run_sync(Base.metadata.create_all)


asyncdefget_async_session()->AsyncGenerator[AsyncSession,None]:
asyncwithasync_session_maker()assession:
yieldsession


asyncdefget_user_db(session:AsyncSession=Depends(get_async_session)):
yieldSQLAlchemyUserDatabase(session,User)

schemas.py

importuuid

fromfastapi_usersimportschemas


classUserRead(schemas.BaseUser[uuid.UUID]):
pass


classUserCreate(schemas.BaseUserCreate):
pass


classUserUpdate(schemas.BaseUserUpdate):
pass

users.py

importuuid
fromtypingimportOptional

fromfastapiimportDepends,Request
fromfastapi_usersimportBaseUserManager,FastAPIUsers,UUIDIDMixin
fromfastapi_users.authenticationimport(
AuthenticationBackend,
BearerTransport,
JWTStrategy,
)
fromfastapi_users.dbimportSQLAlchemyUserDatabase

fromapp.dbimportUser,get_user_db

SECRET="SECRET"


classUserManager(UUIDIDMixin,BaseUserManager[User,uuid.UUID]):
reset_password_token_secret=SECRET
verification_token_secret=SECRET

asyncdefon_after_register(self,user:User,request:Optional[Request]=None):
print(f"User{user.id}hasregistered.")

asyncdefon_after_forgot_password(
self,user:User,token:str,request:Optional[Request]=None
):
print(f"User{user.id}hasforgottheirpassword.Resettoken:{token}")

asyncdefon_after_request_verify(
self,user:User,token:str,request:Optional[Request]=None
):
print(f"Verificationrequestedforuser{user.id}.Verificationtoken:{token}")


asyncdefget_user_manager(user_db:SQLAlchemyUserDatabase=Depends(get_user_db)):
yieldUserManager(user_db)


bearer_transport=BearerTransport(tokenUrl="auth/jwt/login")


defget_jwt_strategy()->JWTStrategy:
returnJWTStrategy(secret=SECRET,lifetime_seconds=3600)


auth_backend=AuthenticationBackend(
name="jwt",
transport=bearer_transport,
get_strategy=get_jwt_strategy,
)

fastapi_users=FastAPIUsers[User,uuid.UUID](get_user_manager,[auth_backend])

current_active_user=fastapi_users.current_user(active=True)

注意: 这些都是fastapi-users官方用例部分,最主要的是 server.py中的结合部分。

fromfastapiimportFastAPI,Depends
fromfastapi.responsesimportRedirectResponse
fromlangserveimportadd_routes

fromcontextlibimportasynccontextmanager

fromapp.dbimportUser,create_db_and_tables
fromapp.schemasimportUserCreate,UserRead,UserUpdate
fromapp.usersimportauth_backend,current_active_user,fastapi_users
fromlangchain.chat_modelsimportChatOpenAI
fromlangchain_community.chat_models.moonshotimportMoonshotChat


@asynccontextmanager
asyncdeflifespan(app:FastAPI):
#NotneededifyousetupamigrationsystemlikeAlembic
awaitcreate_db_and_tables()
yield


app=FastAPI(
lifespan=lifespan,
#dependencies=[Depends(current_active_user)]
)

app.include_router(
fastapi_users.get_auth_router(auth_backend),prefix="/auth/jwt",tags=["auth"]
)
app.include_router(
fastapi_users.get_register_router(UserRead,UserCreate),
prefix="/auth",
tags=["auth"],
)
app.include_router(
fastapi_users.get_reset_password_router(),
prefix="/auth",
tags=["auth"],
)
app.include_router(
fastapi_users.get_verify_router(UserRead),
prefix="/auth",
tags=["auth"],
)
app.include_router(
fastapi_users.get_users_router(UserRead,UserUpdate),
prefix="/users",
tags=["users"],
)


@app.get("/authenticated-route")
asyncdefauthenticated_route(user:User=Depends(current_active_user)):
return{"message":f"Hello{user.email}!"}

add_routes(
app,
MoonshotChat(),
path="/openai",
dependencies=[Depends(current_active_user)],
)

@app.get("/")
asyncdefredirect_root_to_docs():
returnRedirectResponse("/docs")


#Editthistoaddthechainyouwanttoadd
#add_routes(app,NotImplemented)

if__name__=="__main__":
importuvicorn

uvicorn.run(app,host="0.0.0.0",port=8000)

这里,我用的是kimi的api接口,最主要的改变是在add_routes中增加了dependencies参数,引入了fastapi-users封装好的current_active_user。

add_routes(
app,
MoonshotChat(),
path="/openai",
dependencies=[Depends(current_active_user)],#这句代码是关键
)

最后,看下实际调用 invoke 接口后的效果吧!只需要在调用的接口的 header 中加入Authorization即可,对应的值是bearer加 token。这个 token 是调用 login 接口后返回的。



回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

链载AI是专业的生成式人工智能教程平台。提供Stable Diffusion、Midjourney AI绘画教程,Suno AI音乐生成指南,以及Runway、Pika等AI视频制作与动画生成实战案例。从提示词编写到参数调整,手把手助您从入门到精通。
  • 官方手机版

  • 微信公众号

  • 商务合作

  • Powered by Discuz! X3.5 | Copyright © 2025-2025. | 链载Ai
  • 桂ICP备2024021734号 | 营业执照 | |广西笔趣文化传媒有限公司|| QQ