Discord.py v2.0集成OpenAI API的斜杠命令响应超时问题解决
问题分析与解决方案
核心原因
Discord的斜杠命令(交互)确实存在3秒的响应超时限制:用户触发斜杠命令后,机器人必须在3秒内返回至少一个响应(哪怕是临时提示),否则Discord客户端会显示“the application did not respond”。GPT处理复杂查询时响应时间易超过3秒,因此触发该提示。
此外你的代码存在严重问题:ask_ai函数内的while True是死循环,会导致机器人无限重复处理同一个用户查询,进一步加剧超时问题,必须移除。
解决步骤
1. 发送延迟响应延长超时窗口
使用interaction.response.defer()先告知Discord“机器人正在处理,请稍等”,该操作会将超时窗口延长至15分钟,之后通过interaction.followup.send()发送GPT的实际回复。
2. 避免阻塞事件循环
OpenAI官方Python库为同步实现,直接在discord.py的异步函数中调用会阻塞整个机器人的事件循环,导致其他操作无法响应。可通过asyncio.to_thread()将同步的OpenAI调用放到单独线程执行。
3. 修复死循环问题
移除while True循环,你的逻辑无需重复处理同一个查询。
修正后的代码
main.py(保持原代码不变)
import os import asyncio import discord from discord.ext import commands intents = discord.Intents.all() ceriumAI = commands.Bot( command_prefix="<>", intents=intents ) @ceriumAI.event async def on_ready(): print("CeriumAI is ready and online!") @ceriumAI.command() async def sync(ctx): synced = await ceriumAI.tree.sync() print(f"Synced {len(synced)} command(s).") async def loadCogs(): for filename in os.listdir("./Cogs"): if filename.endswith(".py"): await ceriumAI.load_extension(f"Cogs.{filename[:-3]}") print(f"Loaded the cog: {filename[:-3]}") async def main(): await loadCogs() await ceriumAI.start(os.getenv("TOKEN")) asyncio.run(main())
修正后的askai.py
import openai import discord import asyncio from discord import app_commands from discord.ext import commands class Ask_AI(commands.Cog): def __init__(self, ceriumAI): self.ceriumAI = ceriumAI openai.api_key = "MY-API-KEY" # 直接使用模块级别的api_key,无需绑定到self self.messages = [{"role": "system","content":"You are a intelligent assistant."}] @app_commands.command(name="askai") async def ask_ai(self, interaction: discord.Interaction, query: str): # 发送延迟响应,延长超时时间 await interaction.response.defer(ephemeral=False) # ephemeral=False表示所有人可见,True则仅触发用户可见 # 将OpenAI同步调用放入线程,避免阻塞事件循环 def get_gpt_response(): self.messages.append({"role": "user", "content": query}) chat = openai.ChatCompletion.create( model="gpt-3.5-turbo", messages=self.messages, timeout=30 # 添加超时设置 ) reply = chat.choices[0].message.content self.messages.append({"role": "assistant", "content": reply}) return reply try: reply = await asyncio.to_thread(get_gpt_response) # 发送最终回复 await interaction.followup.send(reply) except Exception as e: # 处理API调用异常 await interaction.followup.send(f"处理请求时出错:{str(e)}") async def setup(bot): await bot.add_cog(Ask_AI(bot))
额外说明
defer()的ephemeral参数可按需设置:设为True时仅触发命令的用户可见提示和回复,设为False则频道内所有人可见。- 当前
self.messages为全局对话历史,所有用户查询会共享上下文。若需每个用户独立对话,可改用字典存储,比如self.user_messages = {},通过interaction.user.id区分不同用户的对话记录。
内容的提问来源于stack exchange,提问作者Bhavyadeep Yadav
相关产品推荐
相关产品推荐

