Discord机器人中OpenAI函数调用时类方法无法返回值求助
问题分析与修复方案
核心问题
你的代码存在三个关键问题,导致方法返回值无法被正确获取:
函数字典初始化时立即执行所有方法
你在dict_function中直接调用了self.select_all_quotes()和self.add_quotes(...),这会在字典创建时就强制执行所有方法,而非根据OpenAI返回的function_name按需调用。更严重的是,当请求select_all_quotes时,regex_arguments是"{}",此时尝试获取regex_arguments["amount"]会抛出异常,直接进入except块返回response["content"](值为null),导致data无输出。正则处理后的参数是字符串,未转为字典
re.sub处理后得到的是JSON格式字符串,不是Python字典,直接用regex_arguments["amount"]会触发类型错误。异常捕获范围过大
宽泛的except:会掩盖所有错误,包括参数解析、方法调用异常,导致你无法定位具体问题,误以为是方法返回值的问题。
修复步骤
1. 修改函数字典的定义方式
将字典值改为函数对象,而非直接执行方法,实现按需调用:
dict_function = { "select_all_quotes": self.select_all_quotes, "add_quotes": self.add_quotes }
2. 解析参数字符串为字典
使用json.loads将正则处理后的参数字符串转为字典,兼容空参数场景:
import json # 新增导入json模块 # ... regex_arguments = re.sub(r"\t|\n|\r|\s+", '', response["function_call"]["arguments"]) args = json.loads(regex_arguments) if regex_arguments else {}
3. 按需调用函数并传递参数
根据function_name从字典中取出函数,再根据函数需求传递参数:
function_name = function_call["name"] function = dict_function[function_name] # 针对不同函数传递对应参数 if function_name == "add_quotes": data = function(args["amount"]) else: data = function()
4. 缩小异常捕获范围
只捕获预期异常,保留错误信息便于调试:
try: # ... 你的核心逻辑代码 ... except (KeyError, json.JSONDecodeError, mysql.connector.Error) as e: print(f"错误信息: {e}") return "请求参数错误,请检查输入。" except Exception as e: print(f"未知错误: {e}") return "处理请求时发生异常,请重试。"
5. 修复add_quotes中的query_ai调用
原query_ai方法不支持自定义prompt,需修改以适配获取名言的场景:
def query_ai(self, prompt=None): openai.api_key = savedfile.openai_key() user_content = prompt if prompt else self.query # 获取名言时不需要触发函数调用,仅处理原始用户查询时传入functions参数 functions = function_list() if not prompt else None completion = openai.ChatCompletion.create( model="gpt-3.5-turbo-0613", messages=[ {"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": user_content}, ], functions=functions ) response = completion.choices[0].message # 自定义prompt场景直接返回内容,原始查询返回完整message return response["content"] if prompt else response
完整修复后的关键代码片段
import json # 新增导入 class Quote_Getter(Sql_Query): def __init__(self,query): super().__init__() self.query = query def query_ai(self, prompt=None): openai.api_key = savedfile.openai_key() user_content = prompt if prompt else self.query functions = function_list() if not prompt else None completion = openai.ChatCompletion.create( model="gpt-3.5-turbo-0613", messages=[ {"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": user_content}, ], functions=functions ) response = completion.choices[0].message return response["content"] if prompt else response def query_sort(self): response = self.query_ai() print(response) try: function_call = response["function_call"] regex_arguments = re.sub(r"\t|\n|\r|\s+", '', function_call["arguments"]) print(regex_arguments) args = json.loads(regex_arguments) if regex_arguments else {} dict_function = { "select_all_quotes": self.select_all_quotes, "add_quotes": self.add_quotes } function_name = function_call["name"] function = dict_function[function_name] if function_name == "add_quotes": data = function(args["amount"]) else: data = function() print(data) return data except (KeyError, json.JSONDecodeError) as e: print(f"参数解析错误: {e}") return "请求参数错误,请检查输入。" except Exception as e: print(f"处理错误: {e}") return response.get("content", "无法处理你的请求,请重试。") def answer_back(self): data = self.query_sort() return str(data) def add_quotes(self,amount): data = self.query_ai(f"Get me {amount} motivational quotes") data_list = [line.strip() for line in data.split("\n") if line.strip()] print(data_list) return self.insert_quotes_auto(data_list) # Sql_Query类代码保持不变
验证修复效果
- 请求"显示所有名言"时,代码会执行
select_all_quotes(),正确返回名言列表并发送到Discord。 - 请求"添加5条名言"时,代码会调用
add_quotes(5),获取AI生成的名言后插入数据库,返回插入记录数。
内容的提问来源于stack exchange,提问作者Akashdeep Singh
相关产品推荐
相关产品推荐

