大模型API代币消耗陷阱与成本优化实战指南

📅 2026/7/22 11:31:52
大模型API代币消耗陷阱与成本优化实战指南
最近在折腾大模型 API 调用时我遇到了一个让所有开发者都头疼的问题明明想方设法优化提示词、精简输入输出结果在反复调试的过程中代币消耗反而比预期高出好几倍。这就像为了省油而不断调整驾驶方式最后却发现油表掉得比正常开车还快。这种“省代币反被代币误”的经历背后其实暴露了大模型应用开发中的一个关键认知误区我们往往过于关注单次请求的优化却忽略了迭代调试和错误处理带来的隐性成本。真正的问题不在于如何压缩单次交互的代币用量而在于如何建立一套高效的开发调试流程避免在试错中浪费资源。本文将基于实际项目经验拆解大模型 API 调用中的代币消耗陷阱并提供一套可落地的成本控制方案。无论你是刚开始接触 OpenAI、通义千问等大模型 API 的新手还是已经在生产环境中部署模型服务的老手都能从中找到避免“代币黑洞”的具体方法。1. 为什么省代币反而会花光代币1.1 典型的代币消耗场景分析先来看一个真实案例。假设我们要开发一个智能客服系统需要让大模型理解用户问题并给出专业回答。新手开发者的典型做法是# 错误示范频繁调用完整对话接口进行调试 def ask_question_v1(question): prompt f 你是一个专业的客服助手。请回答用户的问题。 用户问题{question} 请给出专业、准确的回答。 response openai.ChatCompletion.create( modelgpt-3.5-turbo, messages[{role: user, content: prompt}] ) return response.choices[0].message.content # 在调试过程中反复调用 questions [如何重置密码, 订单状态查询, 退款流程] for q in questions: result ask_question_v1(q) print(f问题{q}回答{result})这种方式的代币消耗问题在于每次调用都包含完整的系统提示词重复的提示词结构造成大量冗余没有利用对话历史的上下文压缩1.2 代币消耗的数学原理大模型的代币计费基于输入和输出的总token数。以 GPT-3.5-turbo 为例每1000个token约0.002美元。看似便宜但积少成多单次请求代币数 输入token数 输出token数 月总消耗 Σ(单次请求代币数) × 调用次数 × 单价问题在于调试期间的调用次数往往是生产环境的数十倍。如果每次调试都调用完整接口代币消耗会呈指数级增长。1.3 心理陷阱过度优化反而增加成本开发者常见的心理陷阱包括完美主义陷阱总想找到最优提示词反复微调即时反馈依赖每改一次提示词就立即测试效果忽视工具链手动测试代替自动化验证这些行为模式导致我们在优化的名义下实际上进行了大量低效的探索性调用。2. 大模型 API 代Token计费机制深度解析2.1 Tokenization 的工作原理要真正控制代币消耗首先需要理解文本是如何被转换为token的。以 OpenAI 的 tokenizer 为例# 安装必要的库pip install tiktoken import tiktoken def analyze_tokens(text): encoding tiktoken.get_encoding(cl100k_base) tokens encoding.encode(text) print(f文本长度{len(text)} 字符) print(fToken数量{len(tokens)}) print(fToken列表{tokens}) print(fToken对应文本{[encoding.decode_single_token_bytes(t) for t in tokens]}) return len(tokens) # 测试不同文本的token化效果 texts [ Hello, world!, # 简单英文 你好世界, # 中文 ✨, # 表情符号 ChatGPT API调用最佳实践 # 混合文本 ] for text in texts: print(f\n分析文本{text}) analyze_tokens(text)运行结果会显示中文字符通常1个字符对应1-3个token而表情符号可能占用更多token。这种差异直接影响成本计算。2.2 不同模型的Token成本对比模型输入成本(每1K tokens)输出成本(每1K tokens)上下文长度gpt-3.5-turbo$0.0015$0.00216Kgpt-4$0.03$0.068Kgpt-4-turbo$0.01$0.03128Kclaude-3-sonnet$0.003$0.015200K从表格可以看出模型能力越强代Token成本越高。选择适合任务复杂度的模型是成本控制的第一步。2.3 隐藏的成本陷阱系统提示词与上下文管理很多开发者忽略的是系统提示词在每次对话中都会占用token。如果提示词过长在多轮对话中的累积成本相当可观# 不经济的提示词设计 system_prompt 你是一个资深的技术专家拥有10年以上的软件开发经验。 你擅长Python、Java、JavaScript等多种编程语言。 你在机器学习、深度学习、自然语言处理领域有深入研究。 你能够以清晰、专业的方式解答技术问题。 请确保回答准确、详细并提供代码示例when necessary. # 更经济的提示词设计 optimized_prompt 技术专家回答请专业且提供代码示例。优化前后单次调用就能节省30-50个token。在多轮对话中这种优化效果会不断累积。3. 代Token消耗监控与预警系统搭建3.1 基于装饰器的API调用监控建立监控是成本控制的基础。以下是Python实现的调用监控装饰器import functools import time import tiktoken from datetime import datetime class TokenMonitor: def __init__(self, budget_daily1000): # 每日预算单位千token self.daily_usage 0 self.daily_budget budget_daily self.encoding tiktoken.get_encoding(cl100k_base) def calculate_tokens(self, text): return len(self.encoding.encode(text)) def api_monitor(self, func): functools.wraps(func) def wrapper(*args, **kwargs): # 检查日用量 if self.daily_usage self.daily_budget * 1000: raise Exception(今日代Token预算已用完) start_time time.time() # 估算输入token实际调用前 input_text kwargs.get(prompt, ) or args[0] if args else input_tokens self.calculate_tokens(str(input_text)) try: result func(*args, **kwargs) # 估算输出token output_tokens self.calculate_tokens(str(result)) total_tokens input_tokens output_tokens # 记录使用情况 self.daily_usage total_tokens cost_time time.time() - start_time self._log_usage(func.__name__, input_tokens, output_tokens, total_tokens, cost_time) # 预算预警 if self.daily_usage self.daily_budget * 1000 * 0.8: print(f警告今日预算使用已超过80%) return result except Exception as e: print(fAPI调用失败{e}) # 失败调用也记录输入token self.daily_usage input_tokens raise e return wrapper def _log_usage(self, func_name, input_tokens, output_tokens, total_tokens, cost_time): log_entry { timestamp: datetime.now().isoformat(), function: func_name, input_tokens: input_tokens, output_tokens: output_tokens, total_tokens: total_tokens, cost_time: cost_time, daily_accumulated: self.daily_usage } print(fToken使用记录{log_entry}) # 使用示例 monitor TokenMonitor(budget_daily5) # 每日5K token预算 monitor.api_monitor def chat_completion(prompt): # 模拟API调用 return f模拟响应{prompt[:10]}... # 测试调用 try: response chat_completion(请解释深度学习的基本原理) print(f响应{response}) except Exception as e: print(f调用失败{e})3.2 基于配置文件的预算管理对于团队项目需要更完善的预算管理系统# config/token_budget.yaml daily_budgets: development: 10000 # 开发环境每日10K token testing: 5000 # 测试环境5K token production: 100000 # 生产环境100K token usage_limits: per_request: 2000 # 单次请求最大token数 per_user_hourly: 10000 # 单用户每小时限制 per_project_daily: 50000 # 单项目每日限制 alerts: threshold_80: true # 80%预算时告警 threshold_90: true # 90%预算时告警 threshold_100: true # 100%预算时停止服务# utils/budget_manager.py import yaml import redis from datetime import datetime, timedelta class BudgetManager: def __init__(self, config_pathconfig/token_budget.yaml): with open(config_path, r) as f: self.config yaml.safe_load(f) self.redis_client redis.Redis(hostlocalhost, port6379, db0) def check_budget(self, project_id, user_id, estimated_tokens): # 检查单次请求限制 if estimated_tokens self.config[usage_limits][per_request]: return False, 单次请求token超限 # 检查用户小时限制 user_key fuser:{user_id}:{datetime.now().strftime(%Y%m%d%H)} user_usage int(self.redis_client.get(user_key) or 0) if user_usage estimated_tokens self.config[usage_limits][per_user_hourly]: return False, 用户小时token超限 # 检查项目日限制 project_key fproject:{project_id}:{datetime.now().strftime(%Y%m%d)} project_usage int(self.redis_client.get(project_key) or 0) if project_usage estimated_tokens self.config[usage_limits][per_project_daily]: return False, 项目日token超限 return True, 预算检查通过 def update_usage(self, project_id, user_id, actual_tokens): # 更新各类计数 keys [ fuser:{user_id}:{datetime.now().strftime(%Y%m%d%H)}, fproject:{project_id}:{datetime.now().strftime(%Y%m%d)}, fglobal:{datetime.now().strftime(%Y%m%d)} ] for key in keys: self.redis_client.incrby(key, actual_tokens) # 设置过期时间 if hour in key: self.redis_client.expire(key, 3600) else: self.redis_client.expire(key, 86400)4. 提示词优化与代Token压缩实战技巧4.1 结构化提示词设计模式传统的提示词往往包含大量重复和冗余信息。通过结构化设计可以显著减少token消耗# 优化前的提示词 poor_prompt 请扮演一个经验丰富的软件开发工程师。你擅长多种编程语言包括Python、Java、JavaScript等。 你有10年以上的开发经验参与过大型分布式系统架构设计。 现在请回答以下技术问题如何设计一个高可用的微服务架构 请从服务发现、负载均衡、容错处理、数据一致性等方面详细阐述。 # 优化后的结构化提示词 class StructuredPrompt: def __init__(self): self.role 软件架构师 self.expertise 微服务设计 self.constraints [简洁, 专业, 实用] self.response_format 要点形式 def build_prompt(self, question): # 使用模板减少重复 template f{self.role}||{self.expertise}||{,.join(self.constraints)}||{self.response_format} return f{template}{question} def parse_response(self, response): # 解析结构化的响应 return response.split(|||) if ||| in response else response # 使用示例 prompt_builder StructuredPrompt() optimized_prompt prompt_builder.build_prompt(如何设计高可用微服务架构) print(f优化后提示词{optimized_prompt}) print(fToken节省比例{len(optimized_prompt)/len(poor_prompt)*100:.1f}%)4.2 上下文压缩与摘要技术在多轮对话中之前的对话历史会占用大量token。通过摘要技术可以压缩上下文def summarize_conversation(conversation_history, max_tokens500): 压缩对话历史保留关键信息 if len(conversation_history) 2: # 历史较短时不需要压缩 return conversation_history # 计算当前token数 total_tokens sum(len(tiktoken.encode(msg[content])) for msg in conversation_history) if total_tokens max_tokens: return conversation_history # 需要压缩保留最近几条完整对话之前的进行摘要 recent_messages conversation_history[-3:] # 保留最近3条 older_messages conversation_history[:-3] summary_prompt 请将以下对话历史压缩为简洁的摘要保留关键决策、重要事实和待办事项 {history} 摘要 older_text \n.join([f{msg[role]}: {msg[content]} for msg in older_messages]) summary call_ai_api(summary_prompt.format(historyolder_text)) # 构建压缩后的历史 compressed_history [ {role: system, content: f先前对话摘要{summary}} ] recent_messages return compressed_history # 实际应用示例 long_conversation [ {role: user, content: 我想开发一个在线文档编辑工具}, {role: assistant, content: 好的需要支持哪些功能}, # ... 更多历史消息 ] compressed summarize_conversation(long_conversation) print(f压缩前消息数{len(long_conversation)}) print(f压缩后消息数{len(compressed)})4.3 代码与数据的分离处理当提示词中包含代码或数据时应该采用分离策略def optimize_code_prompt(question, code_snippet): 优化包含代码的提示词 # 不推荐代码直接嵌入提示词 bad_prompt f 请分析以下代码的问题{code_snippet} 问题{question} # 推荐代码与问题分离使用引用 good_prompt f 请分析代码文件中的问题。 代码文件内容 python {code_snippet} 具体问题{question} 请重点关注代码逻辑、性能问题和最佳实践。 return good_prompt # 对于超长代码使用摘要代替完整代码 def create_code_summary_prompt(question, code_path): 对大代码文件生成摘要后再提问 with open(code_path, r) as f: code_content f.read() if len(code_content) 1000: # 代码过长时先摘要 summary_prompt f 请为以下代码生成简洁的功能摘要100字内 {code_content[:2000]} # 只取前2000字符 摘要 code_summary call_ai_api(summary_prompt) final_prompt f 根据代码摘要分析问题 代码功能{code_summary} 问题{question} else: final_prompt optimize_code_prompt(question, code_content) return final_prompt5. 开发调试阶段的代Token节约策略5.1 本地模拟与离线测试在开发初期使用本地模拟可以避免大量API调用# mocks/ai_mock.py class AIMock: def __init__(self, response_patterns): self.patterns response_patterns def chat_completion(self, prompt, **kwargs): # 基于关键词匹配返回模拟响应 for pattern, response in self.patterns.items(): if pattern in prompt.lower(): return self._format_response(response) # 默认响应 return self._format_response(这是一个模拟响应) def _format_response(self, content): return { choices: [ { message: { content: content, role: assistant } } ] } # 使用模拟器进行开发测试 mock_responses { 密码重置: 密码重置流程1. 点击忘记密码 2. 输入邮箱 3. 查收重置链接, 订单查询: 请提供订单号查询最新状态, 退款: 退款申请提交后3-5个工作日处理 } mock_ai AIMock(mock_responses) # 开发阶段使用mock def development_testing(): test_prompts [ 用户问如何重置密码, 订单状态查询流程, 退款需要多长时间 ] for prompt in test_prompts: response mock_ai.chat_completion(prompt) print(f测试提示词{prompt}) print(f模拟响应{response[choices][0][message][content]}\n) # 只有确认逻辑正确后才调用真实API def production_call(prompt): if should_use_real_api(): # 根据条件判断 return openai.ChatCompletion.create( modelgpt-3.5-turbo, messages[{role: user, content: prompt}] ) else: return mock_ai.chat_completion(prompt)5.2 批量测试与自动化验证建立自动化测试套件减少手动调试# tests/prompt_test_suite.py import unittest from unittest.mock import patch from io import StringIO import sys class PromptTestCase(unittest.TestCase): def setUp(self): self.mock_responses { 技术问题: 这是一个技术问题的标准回答模板, 业务咨询: 业务咨询的标准响应流程 } def test_prompt_effectiveness(self): 测试提示词有效性 test_cases [ { prompt: 解释神经网络原理, expected_keywords: [神经元, 层, 激活函数], max_tokens: 150 }, { prompt: 如何优化数据库查询, expected_keywords: [索引, EXPLAIN, 规范化], max_tokens: 200 } ] for case in test_cases: with self.subTest(promptcase[prompt]): result self.simulate_api_call(case[prompt]) self.assertTrue(any(keyword in result for keyword in case[expected_keywords])) self.assertLessEqual(len(result.split()), case[max_tokens]) def simulate_api_call(self, prompt): 模拟API调用避免真实消耗 # 基于规则生成响应不调用真实API if 神经网络 in prompt: return 神经网络由输入层、隐藏层和输出层组成通过激活函数进行非线性变换。 elif 数据库 in prompt: return 数据库优化包括创建合适索引、优化查询语句和规范化设计。 return 标准响应 def test_token_efficiency(self): 测试token使用效率 import tiktoken encoding tiktoken.get_encoding(cl100k_base) prompts [ 简单问题, 这是一个非常详细复杂的问题描述包含大量背景信息和具体要求... ] for prompt in prompts: tokens encoding.encode(prompt) self.assertLess(len(tokens), 100, f提示词过长{len(tokens)} tokens) if __name__ __main__: # 运行测试时不消耗真实token unittest.main(verbosity2)5.3 版本控制与提示词迭代管理使用Git管理提示词版本避免重复实验# 提示词版本管理目录结构 prompts/ ├── versions/ │ ├── v1.0/ │ │ ├── customer_service.md │ │ └── tech_support.md │ ├── v1.1/ │ │ ├── customer_service_optimized.md │ │ └── tech_support_enhanced.md │ └── current - v1.1/ ├── tests/ │ ├── test_customer_service.py │ └── test_tech_support.py └── results/ ├── v1.0_metrics.json └── v1.1_metrics.json# utils/prompt_versioning.py import json import hashlib from pathlib import Path class PromptVersionManager: def __init__(self, prompts_dirprompts): self.prompts_dir Path(prompts_dir) self.versions_dir self.prompts_dir / versions self.results_dir self.prompts_dir / results self.ensure_directories() def ensure_directories(self): self.versions_dir.mkdir(parentsTrue, exist_okTrue) self.results_dir.mkdir(parentsTrue, exist_okTrue) def save_prompt_version(self, prompt_name, content, versionNone): 保存提示词版本 if version is None: version self.generate_version_hash(content) version_dir self.versions_dir / version version_dir.mkdir(exist_okTrue) prompt_file version_dir / f{prompt_name}.md prompt_file.write_text(content, encodingutf-8) # 更新当前版本符号链接 current_link self.prompts_dir / current if current_link.exists(): current_link.unlink() current_link.symlink_to(version_dir) return version def generate_version_hash(self, content): 基于内容生成版本哈希 return hashlib.md5(content.encode()).hexdigest()[:8] def record_test_results(self, version, prompt_name, metrics): 记录测试结果 result_file self.results_dir / f{version}_{prompt_name}.json results { version: version, prompt_name: prompt_name, metrics: metrics, timestamp: datetime.now().isoformat() } result_file.write_text(json.dumps(results, indent2), encodingutf-8) def compare_versions(self, version1, version2, prompt_name): 比较两个版本的性能 try: with open(self.results_dir / f{version1}_{prompt_name}.json) as f: results1 json.load(f) with open(self.results_dir / f{version2}_{prompt_name}.json) as f: results2 json.load(f) comparison { version1: results1[metrics], version2: results2[metrics], improvement: { key: results2[metrics][key] - results1[metrics][key] for key in results1[metrics] } } return comparison except FileNotFoundError: return 测试结果不存在 # 使用示例 manager PromptVersionManager() # 保存新版本提示词 prompt_content 简洁有效地回答技术问题 version manager.save_prompt_version(tech_support, prompt_content) # 记录测试结果 test_metrics { avg_response_tokens: 150, success_rate: 0.95, avg_processing_time: 2.1 } manager.record_test_results(version, tech_support, test_metrics)6. 生产环境中的代Token优化实战6.1 缓存策略实现对于重复或相似的问题使用缓存避免重复调用# utils/response_cache.py import redis import json import hashlib from datetime import timedelta class ResponseCache: def __init__(self, redis_hostlocalhost, redis_port6379): self.redis_client redis.Redis(hostredis_host, portredis_port, db1) self.default_ttl 3600 # 1小时默认缓存时间 def get_cache_key(self, prompt, modelNone, temperature0.7): 生成缓存键 content f{prompt}_{model}_{temperature} return hashlib.md5(content.encode()).hexdigest() def get_cached_response(self, prompt, **kwargs): 获取缓存响应 cache_key self.get_cache_key(prompt, **kwargs) cached self.redis_client.get(cache_key) if cached: return json.loads(cached) return None def set_cached_response(self, prompt, response, ttlNone, **kwargs): 设置缓存 cache_key self.get_cache_key(prompt, **kwargs) ttl ttl or self.default_ttl self.redis_client.setex( cache_key, timedelta(secondsttl), json.dumps(response) ) def cached_api_call(self, api_func, prompt, use_cacheTrue, **kwargs): 带缓存的API调用 if use_cache: cached self.get_cached_response(prompt, **kwargs) if cached: print(使用缓存响应) return cached # 调用真实API response api_func(prompt, **kwargs) if use_cache: self.set_cached_response(prompt, response, **kwargs) return response # 使用示例 cache ResponseCache() def smart_chat_completion(prompt, use_cacheTrue): return cache.cached_api_call( openai.ChatCompletion.create, # 实际API函数 prompt, use_cacheuse_cache, modelgpt-3.5-turbo, temperature0.7 )6.2 请求合并与批量处理将多个小请求合并为单个大请求# utils/batch_processor.py import asyncio from typing import List, Dict import time class BatchProcessor: def __init__(self, max_batch_size10, max_wait_time0.5): self.max_batch_size max_batch_size self.max_wait_time max_wait_time self.batch_queue [] self.processing False async def add_request(self, prompt, callback): 添加请求到批处理队列 self.batch_queue.append({prompt: prompt, callback: callback}) # 检查是否触发处理 if len(self.batch_queue) self.max_batch_size: await self.process_batch() elif not self.processing: asyncio.create_task(self.delayed_process()) async def delayed_process(self): 延迟处理等待更多请求 self.processing True await asyncio.sleep(self.max_wait_time) if self.batch_queue: await self.process_batch() self.processing False async def process_batch(self): 处理当前批次 if not self.batch_queue: return current_batch self.batch_queue[:self.max_batch_size] self.batch_queue self.batch_queue[self.max_batch_size:] # 构建批量提示词 batch_prompts [item[prompt] for item in current_batch] batch_response await self.batch_api_call(batch_prompts) # 分发结果 for i, item in enumerate(current_batch): if i len(batch_response): item[callback](batch_response[i]) async def batch_api_call(self, prompts: List[str]): 批量API调用 # 构建单个包含所有提示词的请求 combined_prompt f 请依次回答以下问题每个回答用---分隔 {chr(10).join([f{i1}. {p} for i, p in enumerate(prompts)])} 请按顺序给出简洁回答。 # 调用API response openai.ChatCompletion.create( modelgpt-3.5-turbo, messages[{role: user, content: combined_prompt}], max_tokenslen(prompts) * 100 # 根据问题数量调整 ) # 解析响应 content response.choices[0].message.content answers content.split(---) return [answer.strip() for answer in answers if answer.strip()] # 使用示例 async def demo_batch_processing(): processor BatchProcessor() async def handle_response(answer): print(f收到响应{answer}) # 添加多个请求 prompts [ Python的基本数据类型有哪些, 如何安装Python包, 什么是虚拟环境, 解释列表和元组的区别 ] for prompt in prompts: await processor.add_request(prompt, handle_response) # 等待处理完成 await asyncio.sleep(1) # asyncio.run(demo_batch_processing())6.3 自适应Token限制策略根据问题复杂度动态调整max_tokens参数# utils/adaptive_tokenizer.py import tiktoken from typing import Tuple class AdaptiveTokenManager: def __init__(self): self.encoding tiktoken.get_encoding(cl100k_base) self.complexity_keywords { high: [解释, 分析, 比较, 优缺点, 原理], medium: [如何, 步骤, 方法, 实现], low: [是什么, 定义, 简单说明] } def estimate_complexity(self, prompt: str) - str: 估计问题复杂度 prompt_lower prompt.lower() for level, keywords in self.complexity_keywords.items(): if any(keyword in prompt_lower for keyword in keywords): return level return medium # 默认中等复杂度 def calculate_optimal_tokens(self, prompt: str, model: str gpt-3.5-turbo) - Tuple[int, int]: 计算最优token限制 input_tokens len(self.encoding.encode(prompt)) complexity self.estimate_complexity(prompt) # 根据复杂度和模型确定输出token限制 base_limits { gpt-3.5-turbo: {low: 100, medium: 300, high: 500}, gpt-4: {low: 150, medium: 400, high: 800} } max_tokens base_limits.get(model, base_limits[gpt-3.5-turbo])[complexity] # 确保不超过模型上限 model_limits {gpt-3.5-turbo: 4096, gpt-4: 8192} max_tokens min(max_tokens, model_limits[model] - input_tokens - 100) # 保留缓冲 return input_tokens, max_tokens def create_optimized_request(self, prompt: str, model: str gpt-3.5-turbo): 创建优化后的API请求参数 input_tokens, max_tokens self.calculate_optimal_tokens(prompt, model) return { model: model, messages: [{role: user, content: prompt}], max_tokens: max_tokens, temperature: 0.7, estimated_input_tokens: input_tokens, estimated_total_tokens: input_tokens max_tokens } # 使用示例 token_manager AdaptiveTokenManager() prompts [ Python是什么, # 低复杂度 如何用Python处理JSON数据, # 中等复杂度 请详细解释Python的垃圾回收机制及其优缺点 # 高复杂度 ] for prompt in prompts: request_params token_manager.create_optimized_request(prompt) print(f问题{prompt}) print(f优化参数{request_params}\n)7. 常见代Token消耗问题与解决方案7.1 问题排查清单问题现象可能原因排查方法解决方案代Token消耗远超预期提示词冗余、调试调用频繁检查API调用日志、分析提示词结构优化提示词、使用缓存、建立调试流程响应内容不完整被截断max_tokens设置过小检查响应长度和token限制动态调整max_tokens、使用流式响应类似问题重复调用API缺乏缓存机制分析请求内容相似度实现响应缓存、请求去重长文档处理成本过高全文传入而非摘要检查输入token数量使用摘要技术、分段处理多轮对话token累积对话历史未压缩分析上下文长度实现历史摘要、定期清理上下文7.2 调试阶段的问题预防# utils/debugging_helper.py class DebuggingHelper: def __init__(self, enabledTrue): self.enabled enabled self.call_history [] def log_api_call(self, prompt, response, tokens_used): 记录API调用日志 if not self.enabled: return log_entry { timestamp: datetime.now().isoformat(), prompt_preview: prompt[:100] ... if len(prompt) 100 else prompt, response_preview: response[:100] ... if len(response) 100 else response,