schroneko commited on
Commit
29d9b4c
·
verified ·
1 Parent(s): 3cb3b9a

Upload app.py

Browse files
Files changed (1) hide show
  1. app.py +187 -0
app.py ADDED
@@ -0,0 +1,187 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import base64
3
+ import os
4
+ from typing import List, Optional, Dict, Any, Tuple
5
+ import anthropic
6
+ import json
7
+ from pathlib import Path
8
+
9
+
10
+ def count_tokens(
11
+ system: str, content: str, tools: str, files: List[gr.File] | None, api_key: str
12
+ ) -> Tuple[Dict, str]:
13
+ try:
14
+ if not content.strip():
15
+ return None, "Error: User Message is required."
16
+
17
+ client = anthropic.Anthropic(
18
+ api_key=api_key.strip()
19
+ if api_key.strip()
20
+ else os.getenv("ANTHROPIC_API_KEY")
21
+ )
22
+
23
+ has_pdf = False
24
+ has_files = bool(files and any(files))
25
+
26
+ if has_files:
27
+ message_content = []
28
+ for file in files:
29
+ if not file:
30
+ continue
31
+
32
+ with open(file.name, "rb") as f:
33
+ file_data = base64.b64encode(f.read()).decode("utf-8")
34
+
35
+ if file.name.lower().endswith(
36
+ (".png", ".jpg", ".jpeg", ".gif", ".webp")
37
+ ):
38
+ message_content.append(
39
+ {
40
+ "type": "image",
41
+ "source": {
42
+ "type": "base64",
43
+ "media_type": f"image/{file.name.split('.')[-1].lower()}",
44
+ "data": file_data,
45
+ },
46
+ }
47
+ )
48
+ elif file.name.lower().endswith(".pdf"):
49
+ message_content.append(
50
+ {
51
+ "type": "document",
52
+ "source": {
53
+ "type": "base64",
54
+ "media_type": "application/pdf",
55
+ "data": file_data,
56
+ },
57
+ }
58
+ )
59
+ has_pdf = True
60
+
61
+ message_content.append({"type": "text", "text": content})
62
+ final_content = message_content
63
+ else:
64
+ final_content = content
65
+
66
+ betas = ["token-counting-2024-11-01"]
67
+ if has_pdf:
68
+ betas.append("pdfs-2024-09-25")
69
+
70
+ params = {
71
+ "betas": betas,
72
+ "model": "claude-3-5-sonnet-20241022",
73
+ "messages": [{"role": "user", "content": final_content}],
74
+ }
75
+
76
+ if system and system.strip():
77
+ params["system"] = system.strip()
78
+
79
+ if tools and tools.strip():
80
+ try:
81
+ params["tools"] = json.loads(tools)
82
+ except json.JSONDecodeError:
83
+ return None, "Error: Invalid JSON format in Tools input"
84
+
85
+ try:
86
+ response = client.beta.messages.count_tokens(**params)
87
+ return params, str(response.input_tokens)
88
+
89
+ except anthropic.APIError as api_error:
90
+ if "system:" in str(api_error):
91
+ params.pop("system", None)
92
+ response = client.beta.messages.count_tokens(**params)
93
+ return (
94
+ params,
95
+ f"{response.input_tokens} (Note: System prompt was ignored)",
96
+ )
97
+ else:
98
+ raise
99
+
100
+ except Exception as e:
101
+ error_msg = str(e)
102
+ if isinstance(e, anthropic.APIError):
103
+ error_msg = f"API Error: {e.message}"
104
+ return None, f"Error: {error_msg}"
105
+
106
+
107
+ def create_demo(api_key: Optional[str] = None) -> gr.Blocks:
108
+ with gr.Blocks(title="Anthropic API Token Counter") as demo:
109
+ gr.Markdown("# Anthropic API Token Counter")
110
+ gr.Markdown("""
111
+ 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).
112
+
113
+ Anthropic API のメッセージのトークン数をカウントします。システムプロンプト、ユーザーメッセージ、ツール、画像、PDFを含むメッセージに対応しています。詳細は[公式ドキュメント](https://docs.anthropic.com/en/docs/build-with-claude/token-counting)を参照してください。API Keyは[Anthropic Console](https://console.anthropic.com/settings/keys)から取得できます。
114
+ """)
115
+
116
+ with gr.Row():
117
+ with gr.Column():
118
+ api_key_input = gr.Textbox(
119
+ label="Anthropic API Key (Required)",
120
+ placeholder="Enter your Anthropic API Key",
121
+ value="",
122
+ type="password",
123
+ )
124
+
125
+ system_input = gr.Textbox(
126
+ label="System Prompt (Optional)",
127
+ placeholder="Enter system prompt if needed",
128
+ lines=3,
129
+ )
130
+
131
+ content_input = gr.Textbox(
132
+ label="User Message (Required)",
133
+ placeholder="Enter the message you want to send to Claude",
134
+ lines=5,
135
+ )
136
+
137
+ tools_input = gr.Textbox(
138
+ label="Tools (Optional)",
139
+ placeholder="""[{
140
+ "name": "get_weather",
141
+ "description": "Get the current weather in a given location",
142
+ "input_schema": {
143
+ "type": "object",
144
+ "properties": {
145
+ "location": {
146
+ "type": "string",
147
+ "description": "The city and state, e.g. San Francisco, CA"
148
+ }
149
+ },
150
+ "required": ["location"]
151
+ }
152
+ }]""",
153
+ lines=8,
154
+ )
155
+
156
+ file_input = gr.File(
157
+ label="Upload Files (Optional) - Images & PDFs",
158
+ file_count="multiple",
159
+ file_types=[".jpg", ".jpeg", ".png", ".gif", ".webp", ".pdf"],
160
+ )
161
+
162
+ count_button = gr.Button("Count Tokens")
163
+
164
+ with gr.Column():
165
+ request_output = gr.JSON(
166
+ label="Request",
167
+ )
168
+ token_output = gr.Textbox(label="Token Count", interactive=False)
169
+
170
+ count_button.click(
171
+ fn=count_tokens,
172
+ inputs=[
173
+ system_input,
174
+ content_input,
175
+ tools_input,
176
+ file_input,
177
+ api_key_input,
178
+ ],
179
+ outputs=[request_output, token_output],
180
+ )
181
+
182
+ return demo
183
+
184
+
185
+ if __name__ == "__main__":
186
+ demo = create_demo()
187
+ demo.launch()