system-prompts-and-models-o.../dealix/autonomous_growth/agents/competitor.py
2026-05-01 14:03:52 +03:00

120 lines
3.9 KiB
Python

"""
Competitor Monitor — summarizes competitor positioning from provided data.
وكيل مراقبة المنافسين — يلخّص وضع المنافسين من البيانات المُقدّمة.
"""
from __future__ import annotations
from dataclasses import dataclass, field
from datetime import datetime
from typing import Any
from core.agents.base import BaseAgent
from core.config.models import Task
from core.llm.base import Message
from core.prompts import get_prompt
from core.utils import generate_id, utcnow
@dataclass
class CompetitorSummary:
id: str
competitor_name: str
locale: str
positioning: str = ""
pricing_hints: str = ""
strengths: list[str] = field(default_factory=list)
weaknesses: list[str] = field(default_factory=list)
counter_moves: list[str] = field(default_factory=list)
summary_markdown: str = ""
created_at: datetime = field(default_factory=utcnow)
def to_dict(self) -> dict[str, Any]:
return {
"id": self.id,
"competitor_name": self.competitor_name,
"locale": self.locale,
"positioning": self.positioning,
"pricing_hints": self.pricing_hints,
"strengths": self.strengths,
"weaknesses": self.weaknesses,
"counter_moves": self.counter_moves,
"summary_markdown": self.summary_markdown,
"created_at": self.created_at.isoformat(),
}
class CompetitorMonitorAgent(BaseAgent):
"""Analyzes competitor info and suggests counter-moves."""
name = "competitor_monitor"
async def run(
self,
*,
competitor_name: str,
competitor_data: str,
locale: str = "ar",
**_: Any,
) -> CompetitorSummary:
"""Summarize competitor, extract counter-moves."""
prompt = get_prompt(
"competitor_summary",
locale=locale,
data=f"Competitor: {competitor_name}\n\n{competitor_data}",
)
response = await self.router.run(
task=Task.REASONING,
messages=[Message(role="user", content=prompt)],
max_tokens=800,
temperature=0.3,
)
markdown = response.content.strip()
summary = CompetitorSummary(
id=generate_id("comp"),
competitor_name=competitor_name,
locale=locale,
summary_markdown=markdown,
)
# Best-effort section extraction
self._populate_sections(summary, markdown)
self.log.info(
"competitor_analyzed",
id=summary.id,
name=competitor_name,
n_weaknesses=len(summary.weaknesses),
)
return summary
@staticmethod
def _populate_sections(summary: CompetitorSummary, markdown: str) -> None:
"""Parse bullet sections loosely."""
lines = markdown.splitlines()
current: list[str] | None = None
for line in lines:
s = line.strip()
lower = s.lower()
if any(t in lower for t in ("strength", "نقاط القوة", "القوة")):
current = summary.strengths
continue
if any(t in lower for t in ("weakness", "نقاط الضعف", "الضعف")):
current = summary.weaknesses
continue
if any(t in lower for t in ("counter", "مضاد", "الحركات المضادة")):
current = summary.counter_moves
continue
if any(t in lower for t in ("pricing", "السعر", "الأسعار")):
summary.pricing_hints = s
current = None
continue
if any(t in lower for t in ("position", "التموضع", "الوضع")):
summary.positioning = s
current = None
continue
if current is not None and (s.startswith("-") or s.startswith("*")):
current.append(s.lstrip("-* ").strip())