Skip to content

Commit 7cf1612

Browse files
authored
Add files via upload
1 parent 6ceaccc commit 7cf1612

1 file changed

Lines changed: 138 additions & 0 deletions

File tree

burn_tokens (3).py

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
"""
2+
API Token Burner — 交互式配置 + 多线程版
3+
"""
4+
5+
import anthropic
6+
import time
7+
import threading
8+
from concurrent.futures import ThreadPoolExecutor, as_completed
9+
10+
lock = threading.Lock()
11+
stats = {"input": 0, "output": 0, "requests": 0, "errors": 0}
12+
stop_flag = threading.Event()
13+
14+
BURN_PROMPT = (
15+
"Explain in detail how the internet works, including TCP/IP, DNS, HTTP, "
16+
"TLS handshake, CDN, load balancing, and BGP routing. "
17+
"Give concrete examples for each concept. Be thorough and detailed."
18+
)
19+
20+
def ask(prompt, default=None, cast=str):
21+
suffix = f" [{default}]" if default is not None else ""
22+
while True:
23+
val = input(f"{prompt}{suffix}: ").strip()
24+
if val == "" and default is not None:
25+
return default
26+
if val == "":
27+
print(" ⚠ 不能为空,请重新输入")
28+
continue
29+
try:
30+
return cast(val)
31+
except ValueError:
32+
print(f" ⚠ 请输入有效的数字")
33+
34+
def single_request(client, model, max_tokens, thread_id):
35+
if stop_flag.is_set():
36+
return
37+
38+
try:
39+
response = client.messages.create(
40+
model=model,
41+
max_tokens=max_tokens,
42+
messages=[{"role": "user", "content": BURN_PROMPT}],
43+
)
44+
in_tok = response.usage.input_tokens
45+
out_tok = response.usage.output_tokens
46+
with lock:
47+
stats["input"] += in_tok
48+
stats["output"] += out_tok
49+
stats["requests"] += 1
50+
total = stats["input"] + stats["output"]
51+
print(f" [T{thread_id:02d}] ✓ in={in_tok:,} out={out_tok:,} | cumulative={total:,}")
52+
53+
except anthropic.RateLimitError:
54+
with lock:
55+
stats["errors"] += 1
56+
print(f" [T{thread_id:02d}] ⚠ Rate limit — waiting 5s...")
57+
time.sleep(5)
58+
59+
except anthropic.APIStatusError as e:
60+
with lock:
61+
stats["errors"] += 1
62+
print(f" [T{thread_id:02d}] ✗ {e.status_code}: {e.message}")
63+
if e.status_code == 402:
64+
stop_flag.set()
65+
raise
66+
67+
except Exception as e:
68+
with lock:
69+
stats["errors"] += 1
70+
print(f" [T{thread_id:02d}] ✗ {type(e).__name__}: {e}")
71+
72+
def print_summary(batch):
73+
print("\n" + "=" * 60)
74+
print(f" Batches : {batch}")
75+
print(f" Requests : {stats['requests']}")
76+
print(f" Errors : {stats['errors']}")
77+
print(f" Input tok : {stats['input']:,}")
78+
print(f" Output tok : {stats['output']:,}")
79+
print(f" Total tok : {stats['input'] + stats['output']:,}")
80+
print("=" * 60)
81+
82+
def main():
83+
print("=" * 60)
84+
print(" API Token Burner — 交互式配置")
85+
print("=" * 60)
86+
print()
87+
88+
base_url = ask("Base URL ", default="https://api.anthropic.com")
89+
api_key = ask("API Key ")
90+
model = ask("Model ", default="claude-haiku-4-5-20251001")
91+
threads = ask("并发线程数 ", default=5, cast=int)
92+
max_tokens = ask("每个请求 output tokens", default=2000, cast=int)
93+
94+
print()
95+
print("=" * 60)
96+
print(f" Base URL : {base_url}")
97+
print(f" Model : {model}")
98+
print(f" Threads : {threads}")
99+
print(f" Max out : {max_tokens} tokens/request")
100+
print("=" * 60)
101+
print(" 开始执行,Ctrl+C 随时停止\n")
102+
103+
client = anthropic.Anthropic(
104+
api_key=api_key,
105+
base_url=base_url,
106+
timeout=120.0,
107+
)
108+
109+
batch = 0
110+
try:
111+
while not stop_flag.is_set():
112+
batch += 1
113+
print(f"--- Batch #{batch} ({threads} concurrent) ---")
114+
with ThreadPoolExecutor(max_workers=threads) as executor:
115+
futures = {
116+
executor.submit(single_request, client, model, max_tokens, i+1): i
117+
for i in range(threads)
118+
}
119+
for future in as_completed(futures):
120+
try:
121+
future.result()
122+
except anthropic.APIStatusError as e:
123+
if e.status_code == 402:
124+
print("\n💸 余额已耗尽!")
125+
stop_flag.set()
126+
127+
if stop_flag.is_set():
128+
break
129+
130+
time.sleep(0.3)
131+
132+
except KeyboardInterrupt:
133+
print("\n⏹ 手动停止。")
134+
135+
print_summary(batch)
136+
137+
if __name__ == "__main__":
138+
main()

0 commit comments

Comments
 (0)