From c5078cc5f880df70c524d15f2c4bb5fd69235c06 Mon Sep 17 00:00:00 2001 From: NguyenND Date: Tue, 30 Jun 2026 11:45:22 -0400 Subject: [PATCH] Jun 30 - Add chat to AI analysis result (content from raw data) --- config.py | 18 ++++++++++++++++++ models.py | 10 ++++++---- routes/ai_summary.py | 24 +++++++++++++++++------- 3 files changed, 41 insertions(+), 11 deletions(-) diff --git a/config.py b/config.py index 2bc299f..8dc29c3 100644 --- a/config.py +++ b/config.py @@ -409,6 +409,24 @@ def initialize_database(): conn.commit() logger.info("Migration: added idx_activity_log_time index to activity_log.") + # ── ai_analysis_log: add document_text column if missing ────────────── + cursor.execute( + """ + SELECT COUNT(*) FROM information_schema.COLUMNS + WHERE TABLE_SCHEMA = DATABASE() + AND TABLE_NAME = 'ai_analysis_log' + AND COLUMN_NAME = 'document_text' + """ + ) + (has_doc_text,) = cursor.fetchone() + if not has_doc_text: + cursor.execute( + "ALTER TABLE ai_analysis_log " + "ADD COLUMN document_text MEDIUMTEXT NULL AFTER criteria_snapshot" + ) + conn.commit() + logger.info("Migration: added document_text column to ai_analysis_log.") + # ── Seed app_settings from environment variables (first-run bootstrap) ─ # Uses INSERT IGNORE so values already saved via the Admin UI are never # overwritten — .env only fills in keys that are completely absent. diff --git a/models.py b/models.py index ed1a524..eb1e6d5 100644 --- a/models.py +++ b/models.py @@ -1367,15 +1367,17 @@ def delete_criterion(admin_id: int, criterion_id: int): def save_ai_analysis(user_id: int, file_names: str, model: str, - verdict, criteria_snapshot, summary_text: str) -> int: + verdict, criteria_snapshot, summary_text: str, + document_text: str = None) -> int: conn = None try: conn = get_connection() cur = conn.cursor() cur.execute( - "INSERT INTO ai_analysis_log (user_id, file_names, model, verdict, criteria_snapshot, summary_text) " - "VALUES (%s,%s,%s,%s,%s,%s)", - (user_id, file_names, model, verdict, criteria_snapshot, summary_text), + "INSERT INTO ai_analysis_log " + "(user_id, file_names, model, verdict, criteria_snapshot, document_text, summary_text) " + "VALUES (%s,%s,%s,%s,%s,%s,%s)", + (user_id, file_names, model, verdict, criteria_snapshot, document_text, summary_text), ) conn.commit() new_id = cur.lastrowid diff --git a/routes/ai_summary.py b/routes/ai_summary.py index d9f73ef..71cee5e 100644 --- a/routes/ai_summary.py +++ b/routes/ai_summary.py @@ -100,7 +100,8 @@ def analyze(): ]) analysis_id = save_ai_analysis( user["id"], ", ".join(file_names), model, - result.get("verdict"), criteria_snap, result.get("summary", "") + result.get("verdict"), criteria_snap, result.get("summary", ""), + document_text=combined, ) log_action(user["id"], "AI_ANALYSIS", "ai_analysis_log", analysis_id, f"AI analysis on {len(file_names)} file(s). Verdict: {result.get('verdict')}.") @@ -472,15 +473,24 @@ def chat(): if not api_key: return jsonify({"error": "Groq API key is not configured."}), 400 - model = get_setting("groq.model", GROQ_MODELS[0]) - summary = (record.get("summary_text") or "")[:8000] + model = get_setting("groq.model", GROQ_MODELS[0]) + + # Prefer raw document text so the AI can answer questions from source material. + # Fall back to the stored summary for analyses run before this feature was added. + raw_text = (record.get("document_text") or "").strip() + if raw_text: + context_label = "ORIGINAL DOCUMENT CONTENT" + context_body = raw_text[:12000] + else: + context_label = "ANALYZED DOCUMENT SUMMARY" + context_body = (record.get("summary_text") or "")[:8000] system_msg = ( "You are a government procurement analyst assistant. " - "The user has questions about a solicitation document that has already been analyzed. " - "Answer questions based solely on the analysis summary below. " - "If the information is not in the summary, say so clearly. Be concise and direct.\n\n" - "## ANALYZED DOCUMENT SUMMARY\n\n" + summary + "The user has questions about a solicitation document. " + "Answer based solely on the document content provided below. " + "If the information is not present, say so clearly. Be concise and direct.\n\n" + f"## {context_label}\n\n" + context_body ) # Sanitize and cap conversation history at 20 turns