Jun 30 - Add chat to AI analysis result (content from raw data)
This commit is contained in:
@@ -409,6 +409,24 @@ def initialize_database():
|
|||||||
conn.commit()
|
conn.commit()
|
||||||
logger.info("Migration: added idx_activity_log_time index to activity_log.")
|
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) ─
|
# ── Seed app_settings from environment variables (first-run bootstrap) ─
|
||||||
# Uses INSERT IGNORE so values already saved via the Admin UI are never
|
# Uses INSERT IGNORE so values already saved via the Admin UI are never
|
||||||
# overwritten — .env only fills in keys that are completely absent.
|
# overwritten — .env only fills in keys that are completely absent.
|
||||||
|
|||||||
@@ -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,
|
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
|
conn = None
|
||||||
try:
|
try:
|
||||||
conn = get_connection()
|
conn = get_connection()
|
||||||
cur = conn.cursor()
|
cur = conn.cursor()
|
||||||
cur.execute(
|
cur.execute(
|
||||||
"INSERT INTO ai_analysis_log (user_id, file_names, model, verdict, criteria_snapshot, summary_text) "
|
"INSERT INTO ai_analysis_log "
|
||||||
"VALUES (%s,%s,%s,%s,%s,%s)",
|
"(user_id, file_names, model, verdict, criteria_snapshot, document_text, summary_text) "
|
||||||
(user_id, file_names, model, verdict, criteria_snapshot, summary_text),
|
"VALUES (%s,%s,%s,%s,%s,%s,%s)",
|
||||||
|
(user_id, file_names, model, verdict, criteria_snapshot, document_text, summary_text),
|
||||||
)
|
)
|
||||||
conn.commit()
|
conn.commit()
|
||||||
new_id = cur.lastrowid
|
new_id = cur.lastrowid
|
||||||
|
|||||||
+17
-7
@@ -100,7 +100,8 @@ def analyze():
|
|||||||
])
|
])
|
||||||
analysis_id = save_ai_analysis(
|
analysis_id = save_ai_analysis(
|
||||||
user["id"], ", ".join(file_names), model,
|
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,
|
log_action(user["id"], "AI_ANALYSIS", "ai_analysis_log", analysis_id,
|
||||||
f"AI analysis on {len(file_names)} file(s). Verdict: {result.get('verdict')}.")
|
f"AI analysis on {len(file_names)} file(s). Verdict: {result.get('verdict')}.")
|
||||||
@@ -472,15 +473,24 @@ def chat():
|
|||||||
if not api_key:
|
if not api_key:
|
||||||
return jsonify({"error": "Groq API key is not configured."}), 400
|
return jsonify({"error": "Groq API key is not configured."}), 400
|
||||||
|
|
||||||
model = get_setting("groq.model", GROQ_MODELS[0])
|
model = get_setting("groq.model", GROQ_MODELS[0])
|
||||||
summary = (record.get("summary_text") or "")[:8000]
|
|
||||||
|
# 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 = (
|
system_msg = (
|
||||||
"You are a government procurement analyst assistant. "
|
"You are a government procurement analyst assistant. "
|
||||||
"The user has questions about a solicitation document that has already been analyzed. "
|
"The user has questions about a solicitation document. "
|
||||||
"Answer questions based solely on the analysis summary below. "
|
"Answer based solely on the document content provided below. "
|
||||||
"If the information is not in the summary, say so clearly. Be concise and direct.\n\n"
|
"If the information is not present, say so clearly. Be concise and direct.\n\n"
|
||||||
"## ANALYZED DOCUMENT SUMMARY\n\n" + summary
|
f"## {context_label}\n\n" + context_body
|
||||||
)
|
)
|
||||||
|
|
||||||
# Sanitize and cap conversation history at 20 turns
|
# Sanitize and cap conversation history at 20 turns
|
||||||
|
|||||||
Reference in New Issue
Block a user