sample1 / app.py
sreepathi-ravikumar's picture
Update app.py
64831ea verified
from flask import Flask, request, Response, jsonify, stream_with_context
from flask_cors import CORS
import os, json, httpx
import config
import base64
from io import BytesIO
import io
from PIL import Image
import requests
app = Flask(__name__)
CORS(app)
OPENROUTER_API_KEY = os.getenv("API_KEYS")
@app.get("/health")
def health():
return jsonify({"status": "ready"}), 200
def _headers():
return {
"Authorization": f"Bearer {OPENROUTER_API_KEY}",
"Content-Type": "application/json",
"HTTP-Referer": "https://YOURSPACE.hf.space",
"X-Title": "Minimal Streaming Test",
}
def upload_image_to_imgbb(image_bytes, filename):
"""Upload image to imgbb with 5 minute expiration and return public URL"""
IMGBB_API_KEY = "22f355dd0069ef8742dc94f0c80e4c4d"
try:
# Convert bytes to base64 for imgbb upload
base64_image = base64.b64encode(image_bytes).decode('utf-8')
response = requests.post(
"https://api.imgbb.com/1/upload",
data={
"key": IMGBB_API_KEY,
"image": base64_image,
"name": filename,
"expiration": 300 # 300 seconds = 5 minutes
},
timeout=10
)
if response.status_code == 200:
return response.json()['data']['url']
else:
print(f"ImgBB error: {response.text}")
return None
except Exception as e:
print(f"Upload error: {e}")
return None
# Fixed _payload: For images, use data[1] directly as the public URL (no prefixing with app URL, since it's now hosted on imgbb).
def _payload(q: str):
data=q.split("%")
content=""
system=""
if data[0]=="Text":
content=data[1]
else:
# For images, content must be an array with text + image
content=[
{
"type": "text",
"text": "Analyze image and get question"
},
{
"type": "image_url",
"image_url": {
"url": data[1] # Direct public URL from imgbb
}
}
]
info=config.config
system=info[data[2]][data[3]]
return {
"model": "meta-llama/llama-4-maverick-17b-128e-instruct",
"stream": True,
"messages": [{"role":"system","content":system},{"role": "user", "content": content}],
"temperature": 0.7,
"top_p":0.9,
"max_tokens": 999,
}
def stream_openrouter(q: str):
if not OPENROUTER_API_KEY:
yield "data: Error: Missing API key\n\n"
return
try:
with httpx.Client(timeout=30.0) as client:
with client.stream("POST",
"https://api.groq.com/openai/v1/chat/completions",
headers=_headers(),
json=_payload(q)) as response:
response.raise_for_status()
for line in response.iter_lines():
if line.startswith('data: '):
data = line[6:] # Remove 'data: ' prefix
if data == '[DONE]':
break
try:
json_data = json.loads(data)
if 'choices' in json_data:
content = json_data['choices'][0].get('delta', {}).get('content')
print(content)
if content:
yield f"data: {json.dumps(content)}\n\n"
except json.JSONDecodeError:
continue
yield "data: [DONE]\n\n"
except httpx.HTTPError as e:
yield f"data: Error: {str(e)}\n\n"
except Exception as e:
yield f"data: Unexpected error: {str(e)}\n\n"
@app.post("/ask")
def ask():
payload = request.get_json(silent=True) or {}
q = payload.get("question", "").strip()
lang = payload.get("selectedLanguage", "").strip()
mode = payload.get("selectedMode", "").strip()
prompt=""
q2lang=""
if not q:
q = "Say hello in one short sentence."
prompt="Text"+"%"+q+"%"+mode+"%"+lang
print(prompt)
return Response(
stream_with_context(stream_openrouter(prompt)),
mimetype="text/event-stream",
headers={
"Cache-Control": "no-cache",
"X-Accel-Buffering": "no"
}
)
# Fixed /askimage endpoint:
# - Use upload_image_to_imgbb to get a public URL instead of saving to local disk (which isn't served statically).
# - Removed invalid 'if not image_url:' check (path is always truthy).
# - Removed local file save.
# - Updated prompt construction to use the public URL directly.
@app.post("/askimage")
def askimage():
# Get form data
image_file = request.files.get('image')
lang = request.form.get('selectedLanguage', '').strip()
mode = request.form.get('selectedMode', '').strip()
if not image_file:
return jsonify({"error": "No image provided"}), 400
try:
# Read image bytes
image_bytes = image_file.read()
# Load image from bytes
img = Image.open(io.BytesIO(image_bytes))
# Resize if larger than 1024x1024 to reduce size (adjust as needed)
max_size = 1024
if img.size[0] > max_size or img.size[1] > max_size:
img.thumbnail((max_size, max_size), Image.Resampling.LANCZOS)
# Save compressed version (quality 85 for balance of speed/size)
output = io.BytesIO()
img.save(output, format='JPEG', quality=85, optimize=True)
compressed_bytes = output.getvalue()
# Use compressed bytes for upload
image_url = upload_image_to_imgbb(compressed_bytes, image_file.filename)
if not image_url:
return jsonify({"error": "Failed to upload image to host"}), 500
# Build prompt with public URL
prompt = "Image"+"%"+image_url+"%"+mode+"%"+lang
print(f"Image URL: {image_url}")
return Response(
stream_with_context(stream_openrouter(prompt)),
mimetype="text/event-stream",
headers={
"Cache-Control": "no-cache",
"X-Accel-Buffering": "no"
}
)
except Exception as e:
return jsonify({"error": str(e)}), 500
if __name__ == "__main__":
app.run(host="0.0.0.0", port=7860, debug=False)