-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapp.py
More file actions
135 lines (106 loc) · 4.74 KB
/
Copy pathapp.py
File metadata and controls
135 lines (106 loc) · 4.74 KB
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
131
132
133
134
135
import os
import json
import requests
from flask import Flask, request, jsonify, send_from_directory
from flask_cors import CORS
from dotenv import load_dotenv
load_dotenv()
app = Flask(__name__, static_folder='.')
CORS(app)
# Configure OpenRouter
OPENROUTER_API_KEY = os.getenv('OPENROUTER_API_KEY')
if not OPENROUTER_API_KEY:
raise ValueError("OPENROUTER_API_KEY not found in environment variables")
SYSTEM_PROMPT = """You are a neutral sentence classifier. Analyze the user's sentence and determine what percentage comes from three sources:
1. Personal Voice (0-100%): Authentic desires, preferences, or statements of personal truth. Uses "I want", "I choose", "I feel", "I believe" in a direct, owned way.
2. Learned Belief (0-100%): Internalized social, familial, or cultural expectations. Often uses "should", "supposed to", "normal", "expected", references to what others think.
3. Fear-Based (0-100%): Motivated by avoidance, loss, risk, or negative outcomes. Contains "but", "what if", "can't afford to", "might fail", catastrophizing language.
The three percentages must sum to 100.
Respond ONLY with valid JSON in this exact format:
{
"personal": <number>,
"learned": <number>,
"fear": <number>,
"explanation": "<one neutral sentence explaining the classification>"
}
Rules:
- No advice, no encouragement, no interpretation beyond classification
- Explanation must be observational, not prescriptive
- If sentence is ambiguous, make reasonable inference
- Keep explanation under 25 words
- Output ONLY the JSON, nothing else"""
@app.route('/')
def index():
return send_from_directory('.', 'index.html')
@app.route('/api/analyze', methods=['POST'])
def analyze():
try:
data = request.get_json()
sentence = data.get('sentence', '').strip()
# Validation
if not sentence:
return jsonify({'error': 'Sentence cannot be empty'}), 400
if len(sentence) < 10:
return jsonify({'error': 'Sentence too short (minimum 10 characters)'}), 400
if len(sentence) > 500:
return jsonify({'error': 'Sentence too long (maximum 500 characters)'}), 400
# Call DeepSeek via OpenRouter
response = requests.post(
url="https://openrouter.ai/api/v1/chat/completions",
headers={
"Authorization": f"Bearer {OPENROUTER_API_KEY}",
"Content-Type": "application/json",
"HTTP-Referer": "https://whose-voice.app",
"X-Title": "Whose Voice",
},
json={
"model": "deepseek/deepseek-r1-0528:free",
"messages": [
{
"role": "system",
"content": SYSTEM_PROMPT
},
{
"role": "user",
"content": f"Classify this sentence: \"{sentence}\""
}
]
},
timeout=60
)
response.raise_for_status()
response_data = response.json()
# Extract content from response
content = response_data['choices'][0]['message']['content'].strip()
# Remove markdown code blocks if present
if content.startswith('```'):
content = content.split('```')[1]
if content.startswith('json'):
content = content[4:]
content = content.strip()
# Remove any trailing backticks
if content.endswith('```'):
content = content[:-3].strip()
result = json.loads(content)
# Normalize percentages to sum to 100
total = result['personal'] + result['learned'] + result['fear']
if total != 100 and total > 0:
result['personal'] = round((result['personal'] / total) * 100)
result['learned'] = round((result['learned'] / total) * 100)
result['fear'] = round((result['fear'] / total) * 100)
# Adjust for rounding errors
diff = 100 - (result['personal'] + result['learned'] + result['fear'])
result['personal'] += diff
return jsonify(result)
except json.JSONDecodeError as e:
print(f"JSON Parse Error: {str(e)}")
return jsonify({'error': 'Unable to analyze this sentence. Please try rephrasing.'}), 500
except requests.exceptions.RequestException as e:
print(f"API Request Error: {str(e)}")
return jsonify({'error': 'Unable to connect to AI service. Please try again.'}), 500
except Exception as e:
print(f"Error: {str(e)}")
return jsonify({'error': 'Unable to analyze this sentence right now. Please try again.'}), 500
if __name__ == '__main__':
port = int(os.getenv('PORT', 8080))
app.run(host='0.0.0.0', port=port, debug=False)