Spaces:
Sleeping
Sleeping
File size: 11,875 Bytes
e6ecc60 |
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 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 |
from flask import render_template, request, jsonify, current_app
from app import db # Assuming db is initialized in app's __init__.py
from app.models import Case, Country, InterrogationSession, GeneratedQuestion, InterrogationResponse, Report, CaseStatus
from app.utils.groq_client import GroqClient
import json
# This will be the main blueprint or directly in app.routes if not using blueprints
# For simplicity, adding routes directly here. In a larger app, use Blueprints.
def register_routes(app):
@app.route('/')
@app.route('/dashboard')
def dashboard():
# Fetch some data for the dashboard
active_cases_count = Case.query.filter_by(status=CaseStatus.ACTIVE).count()
total_interrogations = InterrogationSession.query.count()
completed_reports_count = Report.query.join(Case).filter(Case.status == CaseStatus.COMPLETED).count()
recent_cases = Case.query.order_by(Case.created_at.desc()).limit(5).all()
countries = Country.query.order_by(Country.name).all()
# Placeholder for resolution rate
resolution_rate = "85%" # This would be calculated based on closed/completed cases
return render_template(
'dashboard.html',
active_cases_count=active_cases_count,
total_interrogations=total_interrogations,
completed_reports_count=completed_reports_count,
resolution_rate=resolution_rate,
recent_cases=recent_cases,
countries=countries # Pass countries to the template for selection
)
@app.route('/cases', methods=['GET', 'POST'])
def manage_cases():
if request.method == 'POST':
data = request.form
new_case = Case(
case_id_display=data.get('case_id_display', f"C-NEW-{db.session.query(Case).count() + 1}"), # Generate a simple new ID
case_type=data.get('case_type'),
suspect_name=data.get('suspect_name'),
profile_details=data.get('profile_details'),
evidence_summary=data.get('evidence_summary'),
status=CaseStatus.PENDING, # Default status
country_id=data.get('country_id') # Assuming country_id is passed from form
)
db.session.add(new_case)
db.session.commit()
return jsonify({'message': 'Case created successfully', 'case_id': new_case.id}), 201
cases = Case.query.all()
return render_template('cases.html', cases=cases) # Placeholder, need a cases.html
@app.route('/case/<int:case_id>')
def view_case(case_id):
case = Case.query.get_or_404(case_id)
countries = Country.query.all()
return render_template('case_detail.html', case=case, countries=countries) # Placeholder, need case_detail.html
@app.route('/generate_questions/<int:case_id>', methods=['POST'])
def generate_questions_route(case_id):
case = Case.query.get_or_404(case_id)
if not case.profile_details or not case.evidence_summary:
return jsonify({'error': 'Case profile and evidence summary are required to generate questions.'}), 400
groq_cli = GroqClient()
try:
questions_list = groq_cli.generate_interrogation_questions(
case_details=f"Case Type: {case.case_type}, ID: {case.case_id_display}",
suspect_profile=case.profile_details,
evidence_summary=case.evidence_summary
)
# Store questions in the database
# First, ensure an interrogation session exists or create one
session = InterrogationSession.query.filter_by(case_id=case.id).first()
if not session:
session = InterrogationSession(case_id=case.id, summary_notes="Initial question generation session.")
db.session.add(session)
db.session.commit()
generated_q_objects = []
for q_text in questions_list:
gq = GeneratedQuestion(interrogation_session_id=session.id, question_text=q_text, category="AI Generated")
db.session.add(gq)
generated_q_objects.append({'id': None, 'text': q_text}) # ID will be set after commit
db.session.commit()
# Update IDs after commit
for i, gq_obj in enumerate(GeneratedQuestion.query.filter_by(interrogation_session_id=session.id).order_by(GeneratedQuestion.id.desc()).limit(len(questions_list)).all()):
# This is a bit of a hack to get IDs back, ideally return them from DB operation
if i < len(generated_q_objects):
generated_q_objects[-(i+1)]['id'] = gq_obj.id
return jsonify({'case_id': case.id, 'questions': generated_q_objects}), 200
except Exception as e:
current_app.logger.error(f"Error in /generate_questions/{case_id}: {e}")
return jsonify({'error': str(e)}), 500
@app.route('/generate_report/<int:case_id>', methods=['POST'])
def generate_report_route(case_id):
case = Case.query.get_or_404(case_id)
data = request.json
selected_country_id = data.get('country_id')
interrogation_summary_text = data.get('interrogation_summary', 'No detailed interrogation summary provided by user yet.')
if not selected_country_id:
return jsonify({'error': 'Country ID is required for report generation.'}), 400
selected_country = Country.query.get(selected_country_id)
if not selected_country:
return jsonify({'error': 'Invalid Country ID.'}), 400
# Consolidate interrogation data for the LLM
full_interrogation_summary = interrogation_summary_text # Start with user provided summary
sessions = InterrogationSession.query.filter_by(case_id=case.id).all()
if sessions:
full_interrogation_summary += "\n\n--- Recorded Interrogation Details ---"
for sess_idx, session in enumerate(sessions):
full_interrogation_summary += f"""\nSession {sess_idx+1} (Date: {session.session_date.strftime("%Y-%m-%d")}):\n"""
if session.summary_notes:
full_interrogation_summary += f"Session Notes: {session.summary_notes}\n"
questions = GeneratedQuestion.query.filter_by(interrogation_session_id=session.id).all()
if questions:
full_interrogation_summary += "Questions and Responses:\n"
for q_idx, q in enumerate(questions):
full_interrogation_summary += f" Q{q_idx+1}: {q.question_text}\n"
responses = InterrogationResponse.query.filter_by(generated_question_id=q.id).all()
if responses:
for r_idx, r in enumerate(responses):
full_interrogation_summary += f" A{r_idx+1}: {r.response_text} (Tags: {r.tags or 'N/A'})\n"
else:
full_interrogation_summary += " A: No response recorded.\n"
else:
full_interrogation_summary += "No specific questions recorded for this session.\n"
else:
full_interrogation_summary += "\nNo formal interrogation sessions found in the database for this case."
groq_cli = GroqClient()
try:
report_json_str = groq_cli.generate_report_and_recommendations(
interrogation_summary=full_interrogation_summary,
profile_details=case.profile_details or "Not provided",
evidence_summary=case.evidence_summary or "Not provided",
selected_country_name=selected_country.name
)
# Validate JSON and extract summary for DB
report_content_summary_for_db = "Error parsing LLM JSON output."
recommendations_for_db = "Error parsing LLM JSON output."
try:
report_data = json.loads(report_json_str)
# Extract a brief summary and recommendations for storing in main text fields
# This is a simplified extraction. A more robust parsing would be needed for complex JSON.
cs = report_data.get("caseSummary", {})
if isinstance(cs, dict):
report_content_summary_for_db = cs.get("briefOverview", "Summary not found in JSON.")
else: # if caseSummary is a string directly
report_content_summary_for_db = str(cs)
recom = report_data.get("recommendations", {})
if isinstance(recom, dict):
recommendations_for_db = json.dumps(recom) # Store the whole recommendations object as JSON string
else:
recommendations_for_db = str(recom)
except json.JSONDecodeError as e:
current_app.logger.error(f"Failed to parse report JSON from LLM: {e}. Raw: {report_json_str}")
# report_json_str itself will be stored, and summary/recom will have error messages
# Store the report
new_report = Report(
case_id=case.id,
llm_json_output=report_json_str,
report_content_summary=report_content_summary_for_db,
recommendations=recommendations_for_db,
country_id=selected_country.id
)
db.session.add(new_report)
case.status = CaseStatus.COMPLETED # Optionally update case status
db.session.commit()
return jsonify({'message': 'Report generated successfully', 'report_id': new_report.id, 'raw_json_report': report_json_str}), 200
except Exception as e:
current_app.logger.error(f"Error in /generate_report/{case_id}: {e}")
return jsonify({'error': str(e)}), 500
@app.route('/get_countries', methods=['GET'])
def get_countries():
countries = Country.query.order_by(Country.name).all()
return jsonify([{'id': c.id, 'name': c.name, 'region': c.region} for c in countries])
# Add a route to view a specific report
@app.route('/report/<int:report_id>')
def view_report(report_id):
report = Report.query.get_or_404(report_id)
# The LLM output is stored as a JSON string, parse it for rendering
try:
report_data = json.loads(report.llm_json_output)
except (json.JSONDecodeError, TypeError):
report_data = {"error": "Could not parse report data", "raw": report.llm_json_output}
return render_template('report_detail.html', report=report, report_data=report_data) # Placeholder, need report_detail.html
# Placeholder for other routes from sidebar
@app.route('/interrogations')
def interrogations_page():
sessions = InterrogationSession.query.all()
return render_template('interrogations.html', sessions=sessions) # Placeholder
@app.route('/reports_list') # Renamed to avoid conflict with /report/<id>
def reports_list_page():
reports = Report.query.all()
return render_template('reports_list.html', reports=reports) # Placeholder
@app.route('/regional_guidelines')
def regional_guidelines_page():
countries = Country.query.all()
return render_template('regional_guidelines.html', countries=countries) # Placeholder
# Simple placeholder for other menu items
for item_route in ['team', 'analytics', 'evidence', 'settings', 'help']:
app.add_url_rule(f'/{item_route}', item_route, lambda item_route=item_route: f"{item_route.capitalize()} page coming soon! This is a placeholder.")
|