Álvaro Valenzuela Valdes commited on
Commit ·
be04f48
1
Parent(s): a7c74bb
feat: Enhanced Compra Ágil detection and COT26 pattern matching
Browse files
backend/app/services/llm.py
CHANGED
|
@@ -161,9 +161,9 @@ def generate_analysis(tender: Tender, company: CompanyProfile, document_text: st
|
|
| 161 |
|
| 162 |
# Define Agent roles for separate calls
|
| 163 |
agent_definitions = {
|
| 164 |
-
"legal": "Experto Legal & Cumplimiento: Evalúa bases administrativas, multas y garantías.",
|
| 165 |
-
"tech": "Ingeniero Técnico: Evalúa arquitectura, stack tecnológico y capacidad de ejecución.",
|
| 166 |
-
"risk": "Estratega Comercial: Evalúa rentabilidad, competencia y riesgos de mercado."
|
| 167 |
}
|
| 168 |
|
| 169 |
for agent_id, role_desc in agent_definitions.items():
|
|
|
|
| 161 |
|
| 162 |
# Define Agent roles for separate calls
|
| 163 |
agent_definitions = {
|
| 164 |
+
"legal": "Experto Legal & Cumplimiento: Evalúa bases administrativas, multas y garantías. Pon especial atención a los ANEXOS de Sustentabilidad y Admisibilidad.",
|
| 165 |
+
"tech": "Ingeniero Técnico: Evalúa arquitectura, stack tecnológico y capacidad de ejecución. Considera si se requieren certificaciones ambientales.",
|
| 166 |
+
"risk": "Estratega Comercial: Evalúa rentabilidad, competencia y riesgos de mercado. Analiza el impacto de los criterios de evaluación ESG en el puntaje final."
|
| 167 |
}
|
| 168 |
|
| 169 |
for agent_id, role_desc in agent_definitions.items():
|
frontend/components/AgentAnalysis.tsx
CHANGED
|
@@ -102,6 +102,9 @@ export default function AgentAnalysis({ tender, companyProfile, analysis, onAnal
|
|
| 102 |
<div className="max-w-3xl">
|
| 103 |
<div className="flex items-center gap-3 mb-4">
|
| 104 |
<span className="rounded-full bg-purple-500/20 px-3 py-1 text-[10px] font-bold uppercase tracking-widest text-purple-300 border border-purple-500/30">Active Opportunity</span>
|
|
|
|
|
|
|
|
|
|
| 105 |
<span className="text-xs text-slate-500 font-mono">{tender?.code}</span>
|
| 106 |
</div>
|
| 107 |
<h2 className="text-4xl font-bold text-white tracking-tight leading-tight mb-4">{tender?.name}</h2>
|
|
|
|
| 102 |
<div className="max-w-3xl">
|
| 103 |
<div className="flex items-center gap-3 mb-4">
|
| 104 |
<span className="rounded-full bg-purple-500/20 px-3 py-1 text-[10px] font-bold uppercase tracking-widest text-purple-300 border border-purple-500/30">Active Opportunity</span>
|
| 105 |
+
{tender?.name.toLowerCase().includes('sustentable') || tender?.description?.toLowerCase().includes('ambiental') ? (
|
| 106 |
+
<span className="rounded-full bg-green-500/20 px-3 py-1 text-[10px] font-bold uppercase tracking-widest text-green-400 border border-green-500/30 animate-pulse">🌱 Sustainable / Compra Ágil</span>
|
| 107 |
+
) : null}
|
| 108 |
<span className="text-xs text-slate-500 font-mono">{tender?.code}</span>
|
| 109 |
</div>
|
| 110 |
<h2 className="text-4xl font-bold text-white tracking-tight leading-tight mb-4">{tender?.name}</h2>
|
frontend/components/TenderSearch.tsx
CHANGED
|
@@ -33,6 +33,7 @@ export default function TenderSearch({ tenders, onSearch, onAnalyze, forceShowFo
|
|
| 33 |
|
| 34 |
const [showOnlyFollowed, setShowOnlyFollowed] = useState(forceShowFollowed);
|
| 35 |
const [isLoading, setIsLoading] = useState(false);
|
|
|
|
| 36 |
const itemsPerPage = 50;
|
| 37 |
|
| 38 |
useEffect(() => {
|
|
@@ -92,11 +93,15 @@ export default function TenderSearch({ tenders, onSearch, onAnalyze, forceShowFo
|
|
| 92 |
};
|
| 93 |
|
| 94 |
const filteredTenders = useMemo(() => {
|
|
|
|
| 95 |
if (showOnlyFollowed) {
|
| 96 |
-
|
| 97 |
}
|
| 98 |
-
|
| 99 |
-
|
|
|
|
|
|
|
|
|
|
| 100 |
|
| 101 |
return (
|
| 102 |
<div className="space-y-8 animate-in fade-in slide-in-from-bottom-4 duration-700">
|
|
@@ -162,14 +167,26 @@ export default function TenderSearch({ tenders, onSearch, onAnalyze, forceShowFo
|
|
| 162 |
onChange={(e) => setDate(e.target.value)}
|
| 163 |
/>
|
| 164 |
</div>
|
| 165 |
-
<div className="flex items-end">
|
| 166 |
<button
|
| 167 |
type="submit"
|
| 168 |
disabled={isLoading}
|
| 169 |
-
className="
|
| 170 |
>
|
| 171 |
{isLoading ? "Searching..." : "Fetch Opportunities"}
|
| 172 |
</button>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 173 |
</div>
|
| 174 |
</form>
|
| 175 |
)}
|
|
|
|
| 33 |
|
| 34 |
const [showOnlyFollowed, setShowOnlyFollowed] = useState(forceShowFollowed);
|
| 35 |
const [isLoading, setIsLoading] = useState(false);
|
| 36 |
+
const [isAgileMode, setIsAgileMode] = useState(false);
|
| 37 |
const itemsPerPage = 50;
|
| 38 |
|
| 39 |
useEffect(() => {
|
|
|
|
| 93 |
};
|
| 94 |
|
| 95 |
const filteredTenders = useMemo(() => {
|
| 96 |
+
let list = tenders;
|
| 97 |
if (showOnlyFollowed) {
|
| 98 |
+
list = list.filter(t => followedCodes.includes(t.code));
|
| 99 |
}
|
| 100 |
+
if (isAgileMode) {
|
| 101 |
+
list = list.filter(t => t.code.includes('COT26') || t.name.toLowerCase().includes('compra ágil'));
|
| 102 |
+
}
|
| 103 |
+
return list;
|
| 104 |
+
}, [tenders, showOnlyFollowed, followedCodes, isAgileMode]);
|
| 105 |
|
| 106 |
return (
|
| 107 |
<div className="space-y-8 animate-in fade-in slide-in-from-bottom-4 duration-700">
|
|
|
|
| 167 |
onChange={(e) => setDate(e.target.value)}
|
| 168 |
/>
|
| 169 |
</div>
|
| 170 |
+
<div className="flex items-end gap-3">
|
| 171 |
<button
|
| 172 |
type="submit"
|
| 173 |
disabled={isLoading}
|
| 174 |
+
className="flex-1 premium-gradient hover:opacity-90 text-white font-bold py-3.5 rounded-xl transition-all shadow-lg shadow-purple-500/20 active:scale-[0.98] disabled:opacity-50"
|
| 175 |
>
|
| 176 |
{isLoading ? "Searching..." : "Fetch Opportunities"}
|
| 177 |
</button>
|
| 178 |
+
<button
|
| 179 |
+
type="button"
|
| 180 |
+
onClick={() => setIsAgileMode(!isAgileMode)}
|
| 181 |
+
className={`px-4 py-3.5 rounded-xl border font-bold text-[10px] uppercase tracking-widest transition-all ${
|
| 182 |
+
isAgileMode
|
| 183 |
+
? "bg-cyan/20 border-cyan/40 text-cyan animate-pulse"
|
| 184 |
+
: "bg-white/5 border-white/10 text-slate-500 hover:border-white/20"
|
| 185 |
+
}`}
|
| 186 |
+
title="Toggle Compra Ágil Mode"
|
| 187 |
+
>
|
| 188 |
+
🚀 Agile
|
| 189 |
+
</button>
|
| 190 |
</div>
|
| 191 |
</form>
|
| 192 |
)}
|