schroneko
Refactor codebase
90e9d82
import base64
import json
import os
from typing import Dict, List, Tuple
import anthropic
import gradio as gr
def count_tokens(
system: str, content: str, tools: str, files: List[gr.File] | None, api_key: str
) -> Tuple[Dict, str]:
try:
if not content.strip():
return None, "Error: User Message is required."
client = anthropic.Anthropic(
api_key=api_key.strip()
if api_key.strip()
else os.getenv("ANTHROPIC_API_KEY")
)
has_pdf = False
has_files = bool(files and any(files))
if has_files:
message_content = []
for file in files:
if not file:
continue
with open(file.name, "rb") as f:
file_data = base64.b64encode(f.read()).decode("utf-8")
if file.name.lower().endswith(
(".png", ".jpg", ".jpeg", ".gif", ".webp")
):
message_content.append(
{
"type": "image",
"source": {
"type": "base64",
"media_type": f"image/{file.name.split('.')[-1].lower()}",
"data": file_data,
},
}
)
elif file.name.lower().endswith(".pdf"):
message_content.append(
{
"type": "document",
"source": {
"type": "base64",
"media_type": "application/pdf",
"data": file_data,
},
}
)
has_pdf = True
message_content.append({"type": "text", "text": content})
final_content = message_content
else:
final_content = content
betas = ["token-counting-2024-11-01"]
if has_pdf:
betas.append("pdfs-2024-09-25")
params = {
"betas": betas,
"model": "claude-sonnet-4-5-20250929",
"messages": [{"role": "user", "content": final_content}],
}
if system and system.strip():
params["system"] = system.strip()
if tools and tools.strip():
try:
params["tools"] = json.loads(tools)
except json.JSONDecodeError:
return None, "Error: Invalid JSON format in Tools input"
try:
response = client.beta.messages.count_tokens(**params)
return params, str(response.input_tokens)
except anthropic.APIError as api_error:
if "system:" in str(api_error):
params.pop("system", None)
response = client.beta.messages.count_tokens(**params)
return (
params,
f"{response.input_tokens} (Note: System prompt was ignored)",
)
else:
raise
except Exception as e:
error_msg = str(e)
if isinstance(e, anthropic.APIError):
error_msg = f"API Error: {e.message}"
return None, f"Error: {error_msg}"
def create_demo() -> gr.Blocks:
with gr.Blocks(title="Anthropic API Token Counter") as demo:
gr.Markdown("# Anthropic API Token Counter")
gr.Markdown("""
Count tokens for Anthropic API messages, including system prompts, user messages, tools, images, and PDFs. For more details, see the [official documentation](https://docs.anthropic.com/en/docs/build-with-claude/token-counting). Get your API key from the [Anthropic Console](https://console.anthropic.com/settings/keys).
Anthropic API のメッセージのトークン数をカウントします。システムプロンプト、ユーザーメッセージ、ツール、画像、PDFを含むメッセージに対応しています。詳細は[公式ドキュメント](https://docs.anthropic.com/en/docs/build-with-claude/token-counting)を参照してください。API Keyは[Anthropic Console](https://console.anthropic.com/settings/keys)から取得できます。
""")
with gr.Row():
with gr.Column():
api_key_input = gr.Textbox(
label="Anthropic API Key (Required)",
placeholder="Enter your Anthropic API Key",
value="",
type="password",
)
system_input = gr.Textbox(
label="System Prompt (Optional)",
placeholder="Enter system prompt if needed",
lines=3,
)
content_input = gr.Textbox(
label="User Message (Required)",
placeholder="Enter the message you want to send to Claude",
lines=5,
)
tools_input = gr.Textbox(
label="Tools (Optional)",
placeholder="""[{
"name": "get_weather",
"description": "Get the current weather in a given location",
"input_schema": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The city and state, e.g. San Francisco, CA"
}
},
"required": ["location"]
}
}]""",
lines=8,
)
file_input = gr.File(
label="Upload Files (Optional) - Images & PDFs",
file_count="multiple",
file_types=[".jpg", ".jpeg", ".png", ".gif", ".webp", ".pdf"],
)
count_button = gr.Button("Count Tokens")
with gr.Column():
request_output = gr.JSON(
label="Request",
)
token_output = gr.Textbox(label="Token Count", interactive=False)
count_button.click(
fn=count_tokens,
inputs=[
system_input,
content_input,
tools_input,
file_input,
api_key_input,
],
outputs=[request_output, token_output],
)
return demo
if __name__ == "__main__":
demo = create_demo()
demo.launch()