-
Notifications
You must be signed in to change notification settings - Fork 1.1k
/
app.py
130 lines (108 loc) · 4.24 KB
/
app.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
from flask import Flask, render_template, request, jsonify, url_for
from ce3 import Assistant
import os
from werkzeug.utils import secure_filename
import base64
from config import Config
app = Flask(__name__, static_folder='static')
app.config['UPLOAD_FOLDER'] = 'uploads'
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024 # 16MB max file size
# Ensure upload directory exists
os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True)
# Initialize the assistant
assistant = Assistant()
@app.route('/')
def home():
return render_template('index.html')
@app.route('/chat', methods=['POST'])
def chat():
data = request.json
message = data.get('message', '')
image_data = data.get('image') # Get the base64 image data
# Prepare the message content
if image_data:
# Create a message with both text and image in correct order
message_content = [
{
"type": "image",
"source": {
"type": "base64",
"media_type": "image/jpeg", # We should detect this from the image
"data": image_data.split(',')[1] if ',' in image_data else image_data # Remove data URL prefix if present
}
}
]
# Only add text message if there is actual text
if message.strip():
message_content.append({
"type": "text",
"text": message
})
else:
# Text-only message
message_content = message
try:
# Handle the chat message with the appropriate content
response = assistant.chat(message_content)
# Get token usage from assistant
token_usage = {
'total_tokens': assistant.total_tokens_used,
'max_tokens': Config.MAX_CONVERSATION_TOKENS
}
# Get the last used tool from the conversation history
tool_name = None
if assistant.conversation_history:
for msg in reversed(assistant.conversation_history):
if msg.get('role') == 'assistant' and msg.get('content'):
content = msg['content']
if isinstance(content, list):
for block in content:
if isinstance(block, dict) and block.get('type') == 'tool_use':
tool_name = block.get('name')
break
if tool_name:
break
return jsonify({
'response': response,
'thinking': False,
'tool_name': tool_name,
'token_usage': token_usage
})
except Exception as e:
return jsonify({
'response': f"Error: {str(e)}",
'thinking': False,
'tool_name': None,
'token_usage': None
}), 200 # Return 200 even for errors to handle them gracefully in frontend
@app.route('/upload', methods=['POST'])
def upload_file():
if 'file' not in request.files:
return jsonify({'error': 'No file part'}), 400
file = request.files['file']
if file.filename == '':
return jsonify({'error': 'No selected file'}), 400
if file and file.filename.lower().endswith(('.png', '.jpg', '.jpeg', '.gif', '.webp')):
filename = secure_filename(file.filename)
filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename)
file.save(filepath)
# Get the actual media type
media_type = file.content_type or 'image/jpeg' # Default to jpeg if not detected
# Convert image to base64
with open(filepath, "rb") as image_file:
encoded_string = base64.b64encode(image_file.read()).decode('utf-8')
# Clean up the file
os.remove(filepath)
return jsonify({
'success': True,
'image_data': encoded_string,
'media_type': media_type
})
return jsonify({'error': 'Invalid file type'}), 400
@app.route('/reset', methods=['POST'])
def reset():
# Reset the assistant's conversation history
assistant.reset()
return jsonify({'status': 'success'})
if __name__ == '__main__':
app.run(debug=False)