import asyncio
import uvicorn
from fastapi import FastAPI, BackgroundTasks
from transformers import GPT2LMHeadModel, GPT2Tokenizer
import torch
import random
app = FastAPI()
# 初始化 GPT-2 模型和 tokenizer
model = GPT2LMHeadModel.from_pretrained("gpt2")
tokenizer = GPT2Tokenizer.from_pretrained("gpt2")
# 异步生成文本的函数
async def generate_text(prompt):
input_ids = tokenizer.encode(prompt, return_tensors="pt")
with torch.no_grad():
output = model.generate(input_ids, max_length=100, num_return_sequences=1)
generated_text = tokenizer.decode(output[0], skip_special_tokens=True)
return generated_text
# 异步生成文本的路由
@app.post("/generate-text")
async def generate_text_route(prompt: str):
generated_texts = [] # 定义为局部变量
async with asyncio.Lock(): # 使用异步锁保证线程安全
generated_text = await generate_text(prompt)
generated_texts.append(generated_text)
return {"generated_text": generated_texts[0]} # 返回生成的文本结果
# 启动应用
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=8000)
在异步函数中使用 await
来调用计算密集型任务的函数通常是没有问题的。异步函数主要用于处理 IO 密集型任务,比如网络请求、数据库操作等,而不是用于处理 CPU 计算密集型任务。
在你提到的情况下,如果 generate_text
函数内部执行的是 GPT-2 模型的计算密集型任务,那么在异步函数中使用 await
来调用这个函数可能会导致阻塞,从而影响应用程序的性能和并发能力。
要解决这个问题,可以考虑将计算密集型任务放到一个独立的线程或进程中执行,或者使用异步库来处理这些计算密集型任务,以避免在异步函数中造成阻塞。
下面是一个简单的示例,展示了如何将计算密集型任务放到线程池中执行,并且在异步函数中进行调用:
import asyncio
import uvicorn
from fastapi import FastAPI, BackgroundTasks
from transformers import GPT2LMHeadModel, GPT2Tokenizer
import torch
import random
import concurrent.futures
app = FastAPI()
# 初始化 GPT-2 模型和 tokenizer
model = GPT2LMHeadModel.from_pretrained("gpt2")
tokenizer = GPT2Tokenizer.from_pretrained("gpt2")
# 计算密集型任务,在线程池中执行
def compute_intensive_task(prompt):
input_ids = tokenizer.encode(prompt, return_tensors="pt")
with torch.no_grad():
output = model.generate(input_ids, max_length=100, num_return_sequences=1)
generated_text = tokenizer.decode(output[0], skip_special_tokens=True)
return generated_text
# 异步生成文本的路由
@app.post("/generate-text")
async def generate_text_route(prompt: str):
loop = asyncio.get_running_loop()
# 在线程池中执行计算密集型任务
with concurrent.futures.ThreadPoolExecutor() as pool:
generated_text = await loop.run_in_executor(pool, compute_intensive_task, prompt)
return {"generated_text": generated_text}
# 启动应用
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=8000)
在这个示例中,我们使用了 concurrent.futures.ThreadPoolExecutor
将计算密集型任务 compute_intensive_task
放到线程池中执行,并通过 loop.run_in_executor
在异步函数中调用这个任务,避免了在异步函数中造成阻塞。这样可以提高应用程序的性能和并发能力。