LLM之RAG实战(五十)| FastAPI:构建基于LLM的WEB接口界面

FastAPI是WEB UI接口,随着LLM的蓬勃发展,FastAPI的生态也迎来了新的机遇。本文将围绕FastAPI、OpenAI的API以及FastCRUD,来创建一个个性化的电子邮件写作助手,以展示如何结合这些技术来构建强大的应用程序。
下面我们开始分步骤操作:
一、安装环境
首先,我们创建一个文件夹
mkdir email-assistant-api
进入到该文件夹
cd email-assistant-api
我们使用poetry来管理python包,首先需要先安装poetry
pip install poetry
进入到email-assistant-api文件夹中,并初始化
poetry init
写下所要求的内容(默认为空),然后按 Enter 键

对交互式依赖项键入 no,直到您获得如下内容:

然后只需按 enter 键确认生成。您应该注意到在您的文件夹中创建了一个 pyproject.toml 文件,这是 poetry 用来管理依赖项的文件。
让我们从添加依赖项开始
poetry add fastapi fastcrud sqlmodel openai aiosqlite greenlet python-jose bcrypt
现在你应该还注意到一个 poetry.lock 文件,这是 poetry 保存已安装包的实际版本的方式。
二、项目结构
对于 FastAPI 应用程序,我们有三个主要内容:模型、架构和端点。由于这个 API 很简单,我们可以像这样创建我们的结构:
email_assistant_api/│├── app/│ ├── __init__.py│ ├── main.py # The main application file│ ├── routes.py # Contains API route definitions and endpoint logic│ ├── database.py # Database setup and session management│ ├── models.py # SQLModel models for the application│ ├── crud.py # CRUD operation implementations using FastCRUD│ ├── schemas.py # Schemas for request and response models│ └── .env # Environment variables│├── pyproject.toml # Project configuration and dependencies├── README.md # Provides an overview and documentation└── .gitignore # Files to be ignored by version control
- models.py 中定义我们的模型(数据库表的抽象);
- schemas.py用于验证和序列化数据;
- routes.py定义端点;
- database.py定义数据库相关信息;
- crud.py定义与数据库交互的crud操作;
- .env定义环境变量,比如API Key;
- main.py定义 FastAPI 应用程序和 API 的入口点;
请注意,此结构适用于小型应用程序,但如果您想为大型应用程序提供更强大的模板,请参考:https://github.com/igorbenav/FastAPI-boilerplate
2.1 对数据库进行建模
对于数据库,我们有一个简单的模型
- 用户有一个用户名、一个名字、一个电子邮件,我们存储一个哈希密码。
- 电子邮件日志包含我们为输入定义的内容,以及与此日志关联的用户的时间戳、generated_email 和 ID。
- 用户可能有多个电子邮件日志。

models.py代码示例:
# app/models.pyfrom sqlmodel import SQLModel, Fieldfrom typing import Optionalclass User(SQLModel, table=True):id: Optional[int] = Field(default=None, primary_key=True)name: str = Field(..., min_length=2, max_length=30)username: str = Field(..., min_length=2, max_length=20)email: strhashed_password: strclass EmailLog(SQLModel, table=True):id: Optional[int] = Field(default=None, primary_key=True)user_id: int = Field(foreign_key="user.id")user_input: strreply_to: Optional[str] = Field(default=None)context: Optional[str] = Field(default=None)length: Optional[int] = Field(default=None)tone: strgenerated_email: strtimestamp: str
为了与我们的数据库交互,我们将在 crud.py 中为每个模型实例化 FastCRUD[1]
# app/crud.pyfrom fastcrud import FastCRUDfrom .models import User, EmailLogcrud_user = FastCRUD(User)crud_email_log = FastCRUD(EmailLog)
2.2 创建schemas
schemas.py 中创建我们的 schemas
# app/schemas.pyfrom datetime import datetimefrom typing import Optionalfrom sqlmodel import SQLModel, Field# ------- user -------class UserCreate(SQLModel):name: strusername: stremail: strpassword: strclass UserRead(SQLModel):id: intname: strusername: stremail: strclass UserCreateInternal(SQLModel):name: strusername: stremail: strhashed_password: str# ------- email -------class EmailRequest(SQLModel):user_input: strreply_to: Optional[str] = Nonecontext: Optional[str] = Nonelength: int = 120tone: str = "formal"class EmailResponse(SQLModel):generated_email: str# ------- email log -------class EmailLogCreate(SQLModel):user_id: intuser_input: strreply_to: Optional[str] = Nonecontext: Optional[str] = Nonelength: Optional[int] = Nonetone: Optional[str] = Nonegenerated_email: strtimestamp: datetime = Field(default_factory=lambda: datetime.now(UTC))class EmailLogRead(SQLModel):user_id: intuser_input: strreply_to: Optional[str]context: Optional[str]length: Optional[int]tone: Optional[str]generated_email: strtimestamp: datetime
- 要创建用户,我们要求提供姓名、用户名、电子邮件和密码(我们将存储哈希值);
- 我们将默认长度设置为 120,默认tone设置为 “正式”;
- 我们自动生成 EmailLog 的时间戳
2.3 创建我们的应用程序并设置数据库
尽管我们已经有了模型和架构,但实际上我们既没有为终端节点提供服务的应用程序,也没有用于创建表的数据库。
下面看一下database.py:
# app/database.pyfrom sqlmodel import SQLModel, create_engine, AsyncSessionfrom sqlalchemy.ext.asyncio import create_async_enginefrom sqlalchemy.orm import sessionmakerDATABASE_URL = "sqlite+aiosqlite:///./emailassistant.db"engine = create_async_engine(DATABASE_URL, echo=True)async_session = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)async def create_db_and_tables():async with engine.begin() as conn:await conn.run_sync(SQLModel.metadata.create_all)async def get_session() -> AsyncSession:async with async_session() as session:yield session
在这里,我们连接到了一个 SQLite 数据库,创建了一个函数来创建我们的数据库和表,以及一个允许我们与该数据库交互的会话。
现在让我们最终创建我们的 FastAPI 应用程序:
# app/main.pyfrom fastapi import FastAPIfrom .database import create_db_and_tablesasync def lifespan(app):await create_db_and_tables()yieldapp = FastAPI(lifespan=lifespan)
我们定义lifespan,以便在启动时创建 db 和 tables。
让我们运行一下代码来测试一下:
poetry run fastapi run
结果如下所示:

在浏览器登录如下地址:
127.0.0.1:8000/docs
可以看到如下界面:

可以在终端中按 Ctrl C 暂时关闭应用程序。
2.4 创建端点
接下来,创建端点来生成电子邮件。
首先在 .env 中输入 OpenAI API 密钥(这将被 .gitignore 忽略,并且不会出现在我们的存储库中):
# app/.envOPENAI_API_KEY="my_openai_api_key"
将其写入 .gitignore 以确保不会提交此 API 密钥:
# .gitignore.env.venvenv/venv/ENV/env.bak/venv.bak/
现在从 .env 中获取 OpenAI API 密钥并实例化客户端:
# app/routes.pyimport osfrom starlette.config import Configfrom openai import OpenAIcurrent_file_dir = os.path.dirname(os.path.realpath(__file__))env_path = os.path.join(current_file_dir, ".env")config = Config(env_path)OPENAI_API_KEY = config("OPENAI_API_KEY")open_ai_client = OpenAI(api_key=OPENAI_API_KEY)
为电子邮件终端节点创建一个路由器,并实际为电子邮件创建终端节点:
- 我们将创建一个系统提示符,使输出适应我们想要的结果;
- 我们将创建一个基本提示,用于格式化传递的信息;
- 然后我们将此信息传递给 OpenAI 客户端;
- 最后,我们将在数据库中创建一个日志条目并返回生成的电子邮件
# app/routes.py...from openai import OpenAIfrom fastapi import APIRouter, Depends, HTTPExceptionfrom .schemas import EmailRequest, EmailResponsefrom .database import get_session...# ------- email -------email_router = APIRouter()@email_router.post("/", response_model=EmailResponse)async def generate_email(request: EmailRequest,db: AsyncSession = Depends(get_session)):try:system_prompt = f"""You are a helpful email assistant.You get a prompt to write an email,you reply with the email and nothing else."""prompt = f"""Write an email based on the following input:- User Input: {request.user_input}- Reply To: {request.reply_to if request.reply_to else 'N/A'}- Context: {request.context if request.context else 'N/A'}- Length: {request.length if request.length else 'N/A'} characters- Tone: {request.tone if request.tone else 'N/A'}"""response = await open_ai_client.chat.completions.create(model="gpt-3.5-turbo",messages=[{"role": "system", "content": system_prompt},{"role": "user", "content": prompt},],max_tokens=request.length)generated_email = response.choices[0].message['content'].strip()log_entry = EmailLogCreate(user_id=request.user_id,user_input=request.user_input,reply_to=request.reply_to,context=request.context,length=request.length,tone=request.tone,generated_email=generated_email,)await crud_email_logs.create(db, log_entry)return EmailResponse(generated_email=generated_email)except Exception as e:raise HTTPException(status_code=500, detail=str(e))
现在定义 app/main.py ,将这个电子邮件路由器包含到我们的 FastAPI 应用程序中:
# app/main.pyfrom fastapi import FastAPIfrom .database import create_db_and_tablesfrom .routes import email_routerasync def lifespan(app):await create_db_and_tables()yieldapp = FastAPI(lifespan=lifespan)app.include_router(email_router, prefix="/generate", tags=["Email"])
再次保存并运行 FastAPI 应用程序 (127.0.0.1:8000/docs),会看到如下界面:

点击这个新创建的 post 端点,传递一些信息并单击 execute

可以得到如下内容:

结果是我们所希望的回应,但是目前还无法通过查看日志来判断系统是否正常工作,因此让我们也创建电子邮件日志端点:
# app/routes.py...from fastapi import APIRouter, Depends, HTTPExceptionfrom sqlalchemy.ext.asyncio.session import AsyncSessionfrom .schemas import EmailLogCreate, EmailLogRead...# ------- email log -------log_router = APIRouter()@log_router.get("/")async def read_logs(db: AsyncSession = Depends(get_session)):logs = await crud_email_logs.get_multi(db)return logs@log_router.get("/{log_id}", response_model=EmailLogRead)async def read_log(log_id: int, db: AsyncSession = Depends(get_session)):log = await crud_email_logs.get(db, id=log_id)if not log:raise HTTPException(status_code=404, detail="Log not found")return log
我们可以按其 ID 查看多个日志或一个日志。让我们也将这个路由器包含在我们的应用程序中:
# app/main.pyfrom fastapi import FastAPIfrom .database import create_db_and_tablesfrom .routes import email_router, log_routerasync def lifespan(app):await create_db_and_tables()yieldapp = FastAPI(lifespan=lifespan)app.include_router(email_router, prefix="/generate", tags=["Email"])app.include_router(log_router, prefix="/logs", tags=["Logs"])
三、用户功能、身份验证和安全性
现在,让我们添加实际的用户创建功能。首先在终端上运行:
openssl rand -hex 32
然后将结果写入 .env 作为SECRET_KEY
# app/.envOPENAI_API_KEY="my_openai_api_key"SECRET_KEY="my_secret_key"
首先创建一个文件 helper.py 并将以下代码粘贴到其中:
# app/helper.pyimport osfrom datetime import UTC, datetime, timedeltafrom typing import Any, Annotatedimport bcryptfrom jose import JWTError, jwtfrom fastapi import Depends, HTTPExceptionfrom fastapi.security import OAuth2PasswordBearerfrom sqlalchemy.ext.asyncio import AsyncSessionfrom sqlmodel import SQLModelfrom starlette.config import Configfrom .database import get_sessionfrom .crud import crud_userscurrent_file_dir = os.path.dirname(os.path.realpath(__file__))env_path = os.path.join(current_file_dir, ".env")config = Config(env_path)# Security settingsSECRET_KEY = config("SECRET_KEY")oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/users/login")# Token modelsclass Token(SQLModel):access_token: strtoken_type: strclass TokenData(SQLModel):username_or_email: str# Utility functionsasync def verify_password(plain_password: str, hashed_password: str) -> bool:"""Verify a plain password against a hashed password."""return bcrypt.checkpw(plain_password.encode(), hashed_password.encode())def get_password_hash(password: str) -> str:"""Hash a password."""return bcrypt.hashpw(password.encode(), bcrypt.gensalt()).decode()async def create_access_token(data: dict[str, Any],expires_delta: timedelta | None = None) -> str:"""Create a JWT access token."""to_encode = data.copy()if expires_delta:expire = datetime.now(UTC).replace(tzinfo=None) + expires_deltaelse:expire = datetime.now(UTC).replace(tzinfo=None) + timedelta(minutes=15)to_encode.update({"exp": expire})return jwt.encode(to_encode, SECRET_KEY, algorithm="HS256")async def verify_token(token: str, db: AsyncSession) -> TokenData | None:"""Verify a JWT token and extract the user data."""try:payload = jwt.decode(token, SECRET_KEY, algorithms=["HS256"])username_or_email: str = payload.get("sub")if username_or_email is None:return Nonereturn TokenData(username_or_email=username_or_email)except JWTError:return Noneasync def authenticate_user(username_or_email: str, password: str, db: AsyncSession):if "@" in username_or_email:db_user: dict | None = await crud_users.get(db=db, email=username_or_email, is_deleted=False)else:db_user = await crud_users.get(db=db, username=username_or_email, is_deleted=False)if not db_user:return Falseelif not await verify_password(password, db_user["hashed_password"]):return Falsereturn db_user# Dependencyasync def get_current_user(token: Annotated[str, Depends(oauth2_scheme)],db: Annotated[AsyncSession, Depends(get_session)]) -> dict[str, Any] | None:"""Get the current authenticated user."""token_data = await verify_token(token, db)if token_data is None:raise HTTPException(status_code=401, detail="User not authenticated.")if "@" in token_data.username_or_email:user = await crud_users.get(db=db, email=token_data.username_or_email, is_deleted=False)else:user = await crud_users.get(db=db, username=token_data.username_or_email, is_deleted=False)if user:return userraise HTTPException(status_code=401, detail="User not authenticated.")
- verify_password: 根据哈希密码验证普通密码。它用于检查用户提供的密码是否与存储的哈希密码匹配。
- get_password_hash: 在将用户提供的密码存储到数据库之前对其进行哈希处理。
- create_access_token: 用于为经过身份验证的用户生成 JWT 类型的令牌。
- verify_token: 验证 JWT 令牌并提取用户数据。
- authenticate_user: 负责根据用户的用户名或电子邮件和密码对用户进行身份验证。
- get_current_user: 是一种依赖项,它根据提供的令牌检索当前经过身份验证的用户。
现在,让我们使用这些实用程序函数来创建用户路由。
# app/routes.pyfrom datetime import timedeltafrom fastapi import APIRouter, Depends, HTTPExceptionfrom .database import get_sessionfrom .schemas import UserCreate, UserReadfrom .helper import (get_password_hash,authenticate_user,create_access_token,get_current_user,Token)# ------- user -------user_router = APIRouter()@user_router.post("/register", response_model=UserRead)async def register_user(user: UserCreate,db: AsyncSession = Depends(get_session)):hashed_password = get_password_hash(user.password)user_data = user.dict()user_data["hashed_password"] = hashed_passworddel user_data["password"]new_user = await crud_users.create(db,object=UserCreateInternal(**user_data))return new_user@user_router.post("/login", response_model=Token)async def login_user(user: UserCreate, db: AsyncSession = Depends(get_session)):db_user = await crud_users.get(db, email=user.email)password_verified = await verify_password(user.password, db_user.hashed_password)if not db_user or not password_verified:raise HTTPException(status_code=400, detail="Invalid credentials")access_token_expires = timedelta(minutes=30)access_token = await create_access_token(data={"sub": user["username"]},expires_delta=access_token_expires)return {"access_token": access_token, "token_type": "bearer"}
并将路由器包含在我们的应用程序中:
# app/main.pyfrom fastapi import FastAPIfrom .database import create_db_and_tablesfrom .routes import user_router, email_router, log_routerasync def lifespan(app):await create_db_and_tables()yieldapp = FastAPI(lifespan=lifespan)app.include_router(user_router, prefix="/users", tags=["Users"])app.include_router(email_router, prefix="/generate", tags=["Email"])app.include_router(log_router, prefix="/logs", tags=["Logs"])
最后,让我们在 generate_email 端点中注入 get_current_user 依赖项,添加用户登录以生成电子邮件的需求,此外,还会自动将用户的 ID 存储在日志中:
# app/routes.py...@email_router.post("/", response_model=EmailResponse)async def generate_email(request: EmailRequest,db: AsyncSession = Depends(get_session),current_user: dict = Depends(get_current_user)):try:prompt = f"""Write an email based on the following input:- User Input: {request.user_input}- Reply To: {request.reply_to if request.reply_to else 'N/A'}- Context: {request.context if request.context else 'N/A'}- Length: {request.length if request.length else 'N/A'} characters- Tone: {request.tone if request.tone else 'N/A'}"""response = open_ai_client.chat.completions.create(model="gpt-3.5-turbo",messages=[{"role": "system", "content": "You are a helpful email assistant."},{"role": "user", "content": prompt}],max_tokens=request.length)generated_email = response.choices[0].message.contentlog_entry = EmailLogCreate(user_id=current_user['id'],user_input=request.user_input,reply_to=request.reply_to,context=request.context,length=request.length,tone=request.tone,generated_email=generated_email,)await crud_email_logs.create(db, log_entry)return EmailResponse(generated_email=generated_email)except Exception as e:raise HTTPException(status_code=500, detail=str(e))
如果现在检查终端节点,您将在右侧看到一个小锁。

现在运行程序,需要进行身份验证,您可以通过单击锁并在此处传递有效的用户名和密码(您创建的用户)来完成:

现在,我们还将此依赖项设置为日志端点,此外,让我们使用 FastCRUD 仅过滤当前用户 ID 的日志。
我们可以通过注入 get_current_user 依赖项并将 user_id=current_user[“id”] 传递给 FastCRUD 来实现这一点(当前用户是 get_current_user 返回的)。
...# ------- email log -------log_router = APIRouter()@log_router.get("/")async def read_logs(db: AsyncSession = Depends(get_session),current_user: dict[str, Any] = Depends(get_current_user)):logs = await crud_email_logs.get_multi(db, user_id=current_user["id"])return logs@log_router.get("/{log_id}", response_model=EmailLogRead)async def read_log(log_id: int,db: AsyncSession = Depends(get_session),current_user: dict[str, Any] = Depends(get_current_user)):log = await crud_email_logs.get(db, id=log_id, user_id=current_user["id"])if not log:raise HTTPException(status_code=404, detail="Log not found")return log
现在,我们实际上只能读取我们自己的日志,而且,只有在登录时才能读取。
最终的 routes 文件:
# app/routes.pyimport osfrom typing import Annotated, Anyfrom datetime import timedeltafrom fastapi import APIRouter, Depends, HTTPExceptionfrom fastapi.security import OAuth2PasswordRequestFormfrom sqlalchemy.ext.asyncio.session import AsyncSessionfrom starlette.config import Configfrom openai import OpenAIfrom .crud import crud_email_logs, crud_usersfrom .database import get_sessionfrom .schemas import (EmailRequest,EmailResponse,EmailLogCreate,EmailLogRead,UserCreate,UserRead,UserCreateInternal,)from .helper import (get_password_hash,authenticate_user,create_access_token,get_current_user,Token)current_file_dir = os.path.dirname(os.path.realpath(__file__))env_path = os.path.join(current_file_dir, ".env")config = Config(env_path)OPENAI_API_KEY = config("OPENAI_API_KEY")open_ai_client = OpenAI(api_key=OPENAI_API_KEY)# ------- user -------user_router = APIRouter()@user_router.post("/register", response_model=UserRead)async def register_user(user: UserCreate,db: AsyncSession = Depends(get_session)):hashed_password = get_password_hash(user.password)user_data = user.dict()user_data["hashed_password"] = hashed_passworddel user_data["password"]new_user = await crud_users.create(db,object=UserCreateInternal(**user_data))return new_user@user_router.post("/login", response_model=Token)async def login_user(form_data: Annotated[OAuth2PasswordRequestForm, Depends()],db: AsyncSession = Depends(get_session)):user = await authenticate_user(username_or_email=form_data.username,password=form_data.password,db=db)if not user:raise HTTPException(status_code=400, detail="Invalid credentials")access_token_expires = timedelta(minutes=30)access_token = await create_access_token(data={"sub": user["username"]},expires_delta=access_token_expires)return {"access_token": access_token, "token_type": "bearer"}# ------- email -------email_router = APIRouter()@email_router.post("/", response_model=EmailResponse)async def generate_email(request: EmailRequest,db: AsyncSession = Depends(get_session),current_user: dict = Depends(get_current_user)):try:system_prompt = f"""You are a helpful email assistant.You get a prompt to write an email,you reply with the email and nothing else."""prompt = f"""Write an email based on the following input:- User Input: {request.user_input}- Reply To: {request.reply_to if request.reply_to else 'N/A'}- Context: {request.context if request.context else 'N/A'}- Length: {request.length if request.length else 'N/A'} characters- Tone: {request.tone if request.tone else 'N/A'}"""response = open_ai_client.chat.completions.create(model="gpt-3.5-turbo",messages=[{"role": "system", "content": system_prompt},{"role": "user", "content": prompt}],max_tokens=request.length)generated_email = response.choices[0].message.contentlog_entry = EmailLogCreate(user_id=current_user['id'],user_input=request.user_input,reply_to=request.reply_to,context=request.context,length=request.length,tone=request.tone,generated_email=generated_email,)await crud_email_logs.create(db, log_entry)return EmailResponse(generated_email=generated_email)except Exception as e:raise HTTPException(status_code=500, detail=str(e))# ------- email log -------log_router = APIRouter()@log_router.get("/")async def read_logs(db: AsyncSession = Depends(get_session),current_user: dict[str, Any] = Depends(get_current_user)):logs = await crud_email_logs.get_multi(db, user_id=current_user["id"])return logs@log_router.get("/{log_id}", response_model=EmailLogRead)async def read_log(log_id: int,db: AsyncSession = Depends(get_session),current_user: dict[str, Any] = Depends(get_current_user)):log = await crud_email_logs.get(db, id=log_id, user_id=current_user["id"])if not log:raise HTTPException(status_code=404, detail="Log not found")return log
参考文献:
[1] https://github.com/igorbenav/fastcrud?tab=readme-ov-file
相关文章:
LLM之RAG实战(五十)| FastAPI:构建基于LLM的WEB接口界面
FastAPI是WEB UI接口,随着LLM的蓬勃发展,FastAPI的生态也迎来了新的机遇。本文将围绕FastAPI、OpenAI的API以及FastCRUD,来创建一个个性化的电子邮件写作助手,以展示如何结合这些技术来构建强大的应用程序。 下面我们开始分步骤操…...
项目-移动端适配的几种方案
目录 一、rem方案二、vw适配方案 一、rem方案 以vue2项目为例 下载安装包:npm install amfe-flexible --save在main.js中引入:import ‘amfe-flexible’下载安装包:npm install postcss-pxtorem --save项目下新建postcss.config.js文件&…...
HCIA-Access V2.5_2_2网络通信基础_TCP/IP协议栈报文封装
TCP/IP协议栈的封装过程 用户从应用层发出数据先会交给传输层,传输层会添加TCP或者UDP头部,然后交给网络层,网络层会添加IP头部,然后交给数据链路层,数据链路层会添加以太网头部和以太网尾部,最后变成01这样…...
LSTM详解
1. LSTM设计 LSTM(长短期记忆网络)详解 长短期记忆网络(LSTM, Long Short-Term Memory) 是一种特殊的循环神经网络(RNN),特别适合处理和预测序列数据中的长时间依赖关系。LSTM 通过引入“门机制”(如输入门、遗忘门、输出门)来解决标准 RNN 在长时间序列任务中梯度消…...
从零开始搭建Android开发环境:简单易懂的完整教程
前言: 作为安卓开发的入门,搭建开发环境是每个开发者都必须迈出的第一步。虽然这一步看似简单,但如果没有正确的配置,可能会遇到各种问题。本篇文章将为大家详细介绍如何从零开始搭建Android开发环境,确保你能够顺利开…...
大模型运用-Prompt Engineering(提示工程)
什么是提示工程 提示工程 提示工程也叫指令工程,涉及到如何设计、优化和管理这些Prompt,以确保AI模型能够准确、高效地执行用户的指令,如:讲个笑话、java写个排序算法等 使用目的 1.获得具体问题的具体结果。(如&…...
CMake简单使用(二)
目录 五、scope 作用域5.1 作用域的类型5.1.1 全局作用域5.1.2 目录作用域5.1.3 函数作用域 六、宏6.1 基本语法6.2 演示代码 七、CMake构建项目7.1 全局变量7.2 写入源码路径7.3 调用子目录cmake脚本7.4 CMakeLists 嵌套(最常用) 八、CMake 与库8.1 CMake生成动静态库8.1.1 动…...
攻防世界安卓刷题笔记(新手模式)1-4
1.基础android 进入后是这样的页面。查看源代码看看。首先要注意这个软件并没有加壳,所以我们可以直接着手分析。搜索错误提示“Failed”定位到关键代码,看样子就是检验输入的内容 注意到这里有一行关键代码,cond_39对应的正是failed那个地方…...
发现一个对话框中的按钮,全部失效,点击都没有任何反应,已经解决
前端问题,技术vue2,ts。 发现一个对话框中的按钮,全部失效,点击都没有任何反应。 因为我只在template标签中加入下面这个代码,并没有注册。 只要有一个子组件没有注册,就会影响所有的按钮,使当前…...
MyBatisPlus实现多表查询
在MyBatisPlus中实现多表查询,主要有以下几种方法: 使用注解进行多表查询: 你可以在Mapper接口中使用Select注解来编写SQL查询语句,实现多表查询。例如,如果你想根据用户ID查询用户信息和对应的区域名称,可…...
机器学习详解(5):MLP代码详解之MNIST手写数字识别
文章目录 1 MNIST数据集2 代码详解2.1 导入库和GPU2.2 MNIST数据集处理2.2.1 下载和导入2.2.2 张量(Tensors)2.2.3 准备训练数据 2.3 创建模型2.3.1 图像展开2.3.2 输入层2.3.3 隐藏层2.3.4 输出层2.3.5 模型编译 2.4 训练模型2.4.1 损失函数与优化器2.4.2 计算准确率2.4.3 训练…...
如何在vue中实现父子通信
1.需要用到的组件 父组件 <template><div id"app"><BaseCount :count"count" changeCount"cahngeCount"></BaseCount></div> </template><script> import BaseCount from ./components/BaseCount.v…...
PHP实现华为OBS存储
一:华为OBS存储文档地址 官方文档:https://support.huaweicloud.com/obs/index.html github地址:https://github.com/huaweicloud/huaweicloud-sdk-php-obs 二:安装华为OBS拓展 composer require obs/esdk-obs-php 三&#x…...
嵌入式 linux Git常用命令 抽补丁 打补丁
Git常用命令 为什么要学习git呢?我相信刚入门的小伙伴敲打肯定碰到过这种玄学问题,我明明刚刚还能用的代码,后面不知道咋的就不能用了,所以每次你调出一个功能点以后都会手动复制一份代码防止出问题,时间一长发现整个…...
Alan Chhabra:MongoDB AI应用程序计划(MAAP) 为客户提供价值
MongoDB全球合作伙伴执行副总裁 Alan Chhabra 每当有人向我问询MongoDB,我都会说他们很可能在不觉之间已经与MongoDB有过交集。事实上,包括70%财富百强在内的许多世界领先企业公司都在使用MongoDB。我们在MongoDB所做的一切都是为了服务客户,…...
【学习笔记】目前市面中手持激光雷达设备及参数汇总
手持激光雷达设备介绍 手持激光雷达设备是一种利用激光时间飞行原理来测量物体距离并构建三维模型的便携式高科技产品。它通过发射激光束并分析反射回来的激光信号,能够精确地获取物体的三维结构信息。这种设备以其高精度、适应各种光照环境的能力和便携性…...
Burp与小程序梦中情缘
前言 在日常渗透工作中,有时需要对微信小程序进行抓包渗透,通过抓包,我们可以捕获小程序与服务器之间的通信数据,分析这些数据可以帮助我们发现潜在的安全漏洞,本文通过讲述三个方法在PC端来对小程序抓包渗透 文章目…...
数据结构:Win32 API详解
目录 一.Win32 API的介绍 二.控制台程序(Console)与COORD 1..控制台程序(Console): 2.控制台窗口坐标COORD: 3.GetStdHandle函数: (1)语法: (2)参数: 4.GetConsoleCursorInf…...
迁移学习中模型训练加速(以mllm模型为例),提速15%以上
根据模型训练过程的显存占用实测的分析,一个1g参数的模型(存储占用4g)训练大约需要20g的显存,其中梯度值占用的显存约一半。博主本意是想实现在迁移学习(冻结部分参数)中模型显存占用的降低,结果不太满意,只能实现训练速度提升,但无法实现显存占用优化。预计是在现有的…...
socket编程UDP-实现停等机制(接收确认、超时重传)
在下面博客中,我介绍了利用UDP模拟TCP连接、按数据包发送文件的过程,并附上完整源码。 socket编程UDP-文件传输&模拟TCP建立连接脱离连接(进阶篇)_udp socket发送-CSDN博客 下面博客实现的是滑动窗口机制: sock…...
SpringBoot-17-MyBatis动态SQL标签之常用标签
文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...
铭豹扩展坞 USB转网口 突然无法识别解决方法
当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...
华为云AI开发平台ModelArts
华为云ModelArts:重塑AI开发流程的“智能引擎”与“创新加速器”! 在人工智能浪潮席卷全球的2025年,企业拥抱AI的意愿空前高涨,但技术门槛高、流程复杂、资源投入巨大的现实,却让许多创新构想止步于实验室。数据科学家…...
MFC内存泄露
1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...
【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密
在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...
蓝桥杯 2024 15届国赛 A组 儿童节快乐
P10576 [蓝桥杯 2024 国 A] 儿童节快乐 题目描述 五彩斑斓的气球在蓝天下悠然飘荡,轻快的音乐在耳边持续回荡,小朋友们手牵着手一同畅快欢笑。在这样一片安乐祥和的氛围下,六一来了。 今天是六一儿童节,小蓝老师为了让大家在节…...
【Java_EE】Spring MVC
目录 Spring Web MVC 编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 编辑参数重命名 RequestParam 编辑编辑传递集合 RequestParam 传递JSON数据 编辑RequestBody …...
自然语言处理——循环神经网络
自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元(GRU)长短期记忆神经网络(LSTM)…...
【JavaWeb】Docker项目部署
引言 之前学习了Linux操作系统的常见命令,在Linux上安装软件,以及如何在Linux上部署一个单体项目,大多数同学都会有相同的感受,那就是麻烦。 核心体现在三点: 命令太多了,记不住 软件安装包名字复杂&…...
Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?
在大数据处理领域,Hive 作为 Hadoop 生态中重要的数据仓库工具,其存储格式的选择直接影响数据存储成本、查询效率和计算资源消耗。面对 TextFile、SequenceFile、Parquet、RCFile、ORC 等多种存储格式,很多开发者常常陷入选择困境。本文将从底…...
