脕lvaro Valenzuela Valdes commited on
Commit 路
f80a9d9
1
Parent(s): b3251c0
Fix false positive on questions and make Q&A generation conditional
Browse files
backend/app/services/agents.py
CHANGED
|
@@ -95,8 +95,7 @@ async def run_full_analysis(tender: Tender, company_profile: CompanyProfile, doc
|
|
| 95 |
f" - Propuesta de Valor Diferenciadora (por qu茅 elegirnos)\n"
|
| 96 |
f" - Cronograma estimado\n"
|
| 97 |
f" - Conclusi贸n Profesional\n"
|
| 98 |
-
f"10. requirement_responses: Genera exactamente
|
| 99 |
-
f" Si la licitaci贸n es 'Software de Gesti贸n Municipalidad de Monte Patria', incluye preguntas sobre: integraci贸n, servidores, migraci贸n, soporte 24/7, remuneraciones, firma electr贸nica, tiempos de respuesta, usuarios ilimitados, workflow, capacitaci贸n, motor BD, ISO 27001, respaldos, reportes, etc. hasta completar las 22.\n"
|
| 100 |
f"11. report_markdown: Un reporte general para consumo interno.\n"
|
| 101 |
f"Responde 脷NICAMENTE con el JSON plano. No incluyas explicaciones fuera del JSON."
|
| 102 |
)
|
|
|
|
| 95 |
f" - Propuesta de Valor Diferenciadora (por qu茅 elegirnos)\n"
|
| 96 |
f" - Cronograma estimado\n"
|
| 97 |
f" - Conclusi贸n Profesional\n"
|
| 98 |
+
f"10. requirement_responses: " + (f"Genera exactamente {tender_details.get('metadata', {}).get('question_count', 0)} pares de {{question, answer}} basados en las preguntas reales del mercado. " if tender_details and tender_details.get('metadata', {}).get('question_count', 0) > 0 else "Genera solo 3 preguntas y respuestas basadas en requisitos hipot茅ticos/claves ya que no hay preguntas de mercado activas. ") + "\n"
|
|
|
|
| 99 |
f"11. report_markdown: Un reporte general para consumo interno.\n"
|
| 100 |
f"Responde 脷NICAMENTE con el JSON plano. No incluyas explicaciones fuera del JSON."
|
| 101 |
)
|
backend/app/services/tender_detail_extractor.py
CHANGED
|
@@ -79,10 +79,17 @@ async def extract_tender_detail_tabs(tender_code: str, qs_param: Optional[str] =
|
|
| 79 |
result["metadata"]["has_technical_docs"] = "grvTecnico" in html or html.count("T茅cnico") > 0
|
| 80 |
result["metadata"]["has_economic_docs"] = "grvEconomico" in html or html.count("Econ贸mico") > 0
|
| 81 |
|
| 82 |
-
# Count questions/responses
|
| 83 |
-
questions_match = re.search(r'
|
| 84 |
if questions_match:
|
| 85 |
result["metadata"]["question_count"] = int(questions_match.group(1))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 86 |
|
| 87 |
# Extract adjudication info
|
| 88 |
if "adjudic" in html.lower():
|
|
|
|
| 79 |
result["metadata"]["has_technical_docs"] = "grvTecnico" in html or html.count("T茅cnico") > 0
|
| 80 |
result["metadata"]["has_economic_docs"] = "grvEconomico" in html or html.count("Econ贸mico") > 0
|
| 81 |
|
| 82 |
+
# Count questions/responses (more specific regex for the questions tab label)
|
| 83 |
+
questions_match = re.search(r'id="[^"]*PreguntasLicitacion"[^>]*>.*?(\d+)', html, re.IGNORECASE)
|
| 84 |
if questions_match:
|
| 85 |
result["metadata"]["question_count"] = int(questions_match.group(1))
|
| 86 |
+
else:
|
| 87 |
+
# Fallback to general label if specific ID not found
|
| 88 |
+
questions_match = re.search(r'Preguntas y Respuestas.*?(\d+)', html, re.IGNORECASE)
|
| 89 |
+
if questions_match:
|
| 90 |
+
result["metadata"]["question_count"] = int(questions_match.group(1))
|
| 91 |
+
else:
|
| 92 |
+
result["metadata"]["question_count"] = 0
|
| 93 |
|
| 94 |
# Extract adjudication info
|
| 95 |
if "adjudic" in html.lower():
|
frontend/components/AgentAnalysis.tsx
CHANGED
|
@@ -703,16 +703,18 @@ export default function AgentAnalysis({ tender, companyProfile, analysis, onAnal
|
|
| 703 |
{/* Requirement Q&A Section */}
|
| 704 |
{activeAnalysis.requirement_responses && activeAnalysis.requirement_responses.length > 0 && (
|
| 705 |
<div className="mt-12 space-y-6">
|
| 706 |
-
<div className="flex items-center justify-between border-b border-white/5 pb-4">
|
| 707 |
<div className="flex items-center gap-3">
|
| 708 |
<span className="text-2xl">馃搵</span>
|
| 709 |
-
<h4 className="text-[10px] sm:text-[11px] font-bold uppercase tracking-widest text-purple-400">
|
|
|
|
|
|
|
| 710 |
</div>
|
| 711 |
-
|
| 712 |
-
<
|
| 713 |
-
|
| 714 |
-
|
| 715 |
-
|
|
|
|
| 716 |
<div className="grid gap-4 max-h-[600px] overflow-y-auto pr-4 custom-scrollbar">
|
| 717 |
{activeAnalysis.requirement_responses.map((item, i) => (
|
| 718 |
<div key={i} className="rounded-2xl bg-white/[0.03] border border-white/5 p-4 sm:p-6 hover:border-purple-500/30 transition-all group">
|
|
|
|
| 703 |
{/* Requirement Q&A Section */}
|
| 704 |
{activeAnalysis.requirement_responses && activeAnalysis.requirement_responses.length > 0 && (
|
| 705 |
<div className="mt-12 space-y-6">
|
|
|
|
| 706 |
<div className="flex items-center gap-3">
|
| 707 |
<span className="text-2xl">馃搵</span>
|
| 708 |
+
<h4 className="text-[10px] sm:text-[11px] font-bold uppercase tracking-widest text-purple-400">
|
| 709 |
+
{activeAnalysis.requirement_responses.length > 3 ? `Actual Market Questions (${activeAnalysis.requirement_responses.length})` : "Intelligence Requirement Response"}
|
| 710 |
+
</h4>
|
| 711 |
</div>
|
| 712 |
+
{activeAnalysis.requirement_responses.length > 3 && (
|
| 713 |
+
<div className="flex items-center gap-2 px-3 py-1 rounded-full bg-green-500/10 border border-green-500/20">
|
| 714 |
+
<span className="w-1.5 h-1.5 rounded-full bg-green-500 animate-pulse" />
|
| 715 |
+
<span className="text-[9px] font-bold text-green-400 uppercase tracking-tighter">Synced with Portal</span>
|
| 716 |
+
</div>
|
| 717 |
+
)}
|
| 718 |
<div className="grid gap-4 max-h-[600px] overflow-y-auto pr-4 custom-scrollbar">
|
| 719 |
{activeAnalysis.requirement_responses.map((item, i) => (
|
| 720 |
<div key={i} className="rounded-2xl bg-white/[0.03] border border-white/5 p-4 sm:p-6 hover:border-purple-500/30 transition-all group">
|