AI 기반 경쟁 정보 모니터 구축
I’m happy to translate the article for you, but I’ll need the full text you’d like translated. Could you please paste the content (or the portions you want translated) here? I’ll keep the source link at the top exactly as you requested and preserve all formatting, markdown, and technical terms.
Competitive Intelligence Monitor
경쟁자를 앞서 나가기 위해서는 지속적인 경계가 필요합니다—제품 출시, 투자 라운드, 파트너십 및 전략적 움직임을 웹 전반에 걸쳐 추적합니다. 오픈‑소스 Competitive Intelligence Monitor 프로젝트는 CocoIndex, Tavily Search, 그리고 LLM 추출을 활용하여 이 과정을 자동화하고, 경쟁자 뉴스를 지속적으로 추적·구조화하여 쿼리 가능한 PostgreSQL 데이터베이스에 저장하는 방법을 보여줍니다.
작동 방식
시스템은 웹 모니터링을 자동화합니다:
- Tavily AI Search – 전체 텍스트 기사를 가져옵니다.
- LLM Extraction (GPT‑4o‑mini) – 구조화된 “경쟁 이벤트”를 감지합니다.
- PostgreSQL – 이벤트와 원본 기사를 저장하여 쿼리 기반 인텔리전스를 제공합니다.
추출된 이벤트 유형
- 제품 출시 및 기능 릴리스
- 파트너십 및 협업
- 투자 라운드 및 재무 뉴스
- 주요 임원 채용 / 퇴사
- 인수 및 합병
이러한 이벤트와 원본 기사는 PostgreSQL에 저장되어 팀이 다음과 같은 자연어 질문을 할 수 있습니다:
- “Anthropic은 최근에 무엇을 하고 있나요?”
- “이번 주에 가장 많은 뉴스를 내는 경쟁자는 누구인가요?”
아키텍처 다이어그램
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Tavily AI │────▶│ CocoIndex │────▶│ PostgreSQL │
│ Search │ │ Pipeline │ │ Database │
└──────────────┘ └──────────────┘ └──────────────┘
│ │ │
▼ ▼ ▼
Articles Extraction Intelligence
(web data) (GPT‑4o‑mini) (structured)
데이터는 Tavily 검색 결과에서 LLM 추출 단계로 흐르며 CompetitiveEvent 객체를 생성한 뒤, 원본 기사용 테이블 하나와 정규화된 이벤트용 테이블 하나, 두 개의 테이블에 저장됩니다.
데이터 모델
import dataclasses
@dataclasses.dataclass
class CompetitiveEvent:
"""A competitive intelligence event extracted from text.
Examples:
- Product Launch: "OpenAI released GPT‑5 with multimodal capabilities"
- Partnership: "Anthropic partnered with Google Cloud for enterprise AI"
- Funding: "Mistral AI raised $400M Series B led by Andreessen Horowitz"
- Key Hire: "Former Meta AI director joined Cohere as Chief Scientist"
- Strategic Move: "Microsoft acquired AI startup Inflection for $650M"
"""
event_type: str # "product_launch", "partnership", "funding",
# "key_hire", "acquisition", "other"
competitor: str # Company name (e.g., "OpenAI")
description: str # Brief description of the event
significance: str # "high", "medium", "low"
related_companies: list[str] # Other companies mentioned
타빌리 검색 소스 커넥터
class TavilySearchSource(SourceSpec):
"""Fetches competitive intelligence using Tavily AI Search API."""
competitor: str
days_back: int = 7
max_results: int = 10
@source_connector(
spec_cls=TavilySearchSource,
key_type=_ArticleKey,
value_type=_Article,
)
class TavilySearchConnector:
async def list(self) -> AsyncIterator[PartialSourceRow[_ArticleKey, _Article]]:
"""List articles from Tavily search."""
search_query = (
f"{self._spec.competitor} AND "
f"(funding OR partnership OR product launch OR acquisition OR executive hire)"
)
client = TavilyClient(api_key=self._api_key)
response = client.search(
query=search_query,
search_depth="advanced",
max_results=self._spec.max_results,
include_raw_content=True,
)
for ordinal, result in enumerate(response.get("results", [])):
url = result["url"]
yield PartialSourceRow(
key=_ArticleKey(url=url),
data=PartialSourceRowData(ordinal=ordinal),
)
메인 파이프라인 (CocoIndex 흐름)
@cocoindex.flow_def(name="CompetitiveIntelligence")
def competitive_intelligence_flow(
flow_builder: cocoindex.FlowBuilder, data_scope: cocoindex.DataScope
) -> None:
"""Main pipeline for competitive intelligence monitoring."""
competitors = os.getenv("COMPETITORS", "OpenAI,Anthropic").split(",")
refresh_interval = int(os.getenv("REFRESH_INTERVAL_SECONDS", "3600"))
# Add Tavily search source for each competitor
for competitor in competitors:
data_scope[f"articles_{competitor.strip()}"] = flow_builder.add_source(
TavilySearchSource(
competitor=competitor.strip(),
days_back=7,
max_results=10,
),
refresh_interval=timedelta(seconds=refresh_interval),
)
articles_index = data_scope.add_collector()
events_index = data_scope.add_collector()
# Process each competitor's articles
for competitor in competitors:
articles = data_scope[f"articles_{competitor.strip()}"]
with articles.row() as article:
# Extract competitive events using GPT‑4o‑mini via OpenRouter
article["events"] = article["content"].transform(
cocoindex.functions.ExtractByLlm(
llm_spec=cocoindex.LlmSpec(
api_type=cocoindex.LlmApiType.OPENAI,
model="openai/gpt-4o-mini",
address="https://openrouter.ai/api/v1",
),
output_type=list[CompetitiveEvent],
instruction=(
"Extract competitive intelligence events from this article. "
"Focus on: product launches, partnerships, funding rounds, "
"key hires, acquisitions, and other strategic moves."
),
)
)
쿼리 핸들러
@competitive_intelligence_flow.query_handler()
def search_events(query: str) -> list[dict]:
"""
PostgreSQL 저장소에 대해 자연어 쿼리를 실행합니다.
예시 쿼리:
- "Anthropic이 이번 달에 발표한 제품 출시가 무엇인가요?"
- "지난 주에 경쟁사들의 모든 펀딩 라운드를 나열해 주세요."
"""
# 구현은 간략히 생략했습니다 – LLM을 사용한 SQL 생성.
pass
Source:
요약
- Tavily AI는 대상 경쟁사에 대한 최신 웹 기사를 수집합니다.
- CocoIndex는 파이프라인을 조정하고 GPT‑4o‑mini 추출을 실행하여 구조화된 CompetitiveEvent 레코드를 생성합니다.
- 모든 원시 기사와 정규화된 이벤트는 PostgreSQL에 저장되어, 자연어 질의와 대시보드를 통해 지속적인 경쟁 인텔리전스를 제공할 수 있습니다.
def ch_by_competitor(
competitor: str,
event_type: str | None = None,
limit: int = 20,
) -> cocoindex.QueryOutput:
"""Find recent competitive intelligence about a specific competitor."""
with connection_pool().connection() as conn:
with conn.cursor() as cur:
sql = f"""
SELECT e.competitor,
e.event_type,
e.description,
e.significance,
e.related_companies,
a.title,
a.url,
a.source,
a.published_at
FROM {events_table} e
JOIN {articles_table} a ON e.article_id = a.id
WHERE LOWER(e.competitor) LIKE LOWER(%s)
"""
params = [f"%{competitor}%"]
if event_type:
sql += " AND e.event_type = %s"
params.append(event_type)
sql += " ORDER BY a.published_at DESC LIMIT %s"
cur.execute(sql, params)
return cocoindex.QueryOutput(results=[...])
구성 (환경 변수)
DATABASE_URL=postgresql://user:password@localhost:5432/competitive_intel
COCOINDEX_DATABASE_URL=postgresql://user:password@localhost:5432/competitive_intel
OPENAI_API_KEY=sk-or-v1-...
TAVILY_API_KEY=tvly-...
COMPETITORS=OpenAI,Anthropic,Google AI,Meta AI,Mistral AI
REFRESH_INTERVAL_SECONDS=3600
SEARCH_DAYS_BACK=7
최초 설정
python3 run_interactive.py
자동 배포 (CocoIndex)
cocoindex update main -f # Initial sync
cocoindex update -L main.py # Continuous monitoring
모니터 작동 방식
- AI‑native search – Tavily는 기사 내용을 추출하여 깨지기 쉬운 스크래핑을 피합니다.
- De‑duplication – CocoIndex는 증분 처리 방식을 통해 처리된 기사를 추적합니다.
- Signal extraction – 구조화된 이벤트는 중요도에 따라 점수가 매겨집니다.
- Flexible analysis – 이중 인덱싱(원본 + 추출)으로 최대 유연성을 제공합니다.
지원되는 쿼리 유형
- 경쟁사 이름으로 검색
- 이벤트 유형별 필터링 (펀딩, 파트너십, 인수 등)
- 중요도에 따라 순위 매기기 (high = 3, medium = 2, low = 1 가중 점수)
- 기간별 트렌드 분석
프로젝트 개요
경쟁 정보 모니터
AI 기반 검색 및 LLM 추출을 활용해 웹 전반에서 경쟁자 언급을 추적합니다. 파이프라인은 자동으로:
- Tavily AI(에이전트에 최적화)로 웹 검색
- DeepSeek LLM 분석으로 경쟁 정보 이벤트 추출
- 원본 기사와 추출된 이벤트를 PostgreSQL에 색인
캡처되는 이벤트 유형
- 제품 출시 및 기능 릴리스
- 파트너십 및 협업
- 투자 라운드 및 재무 뉴스
- 주요 임원 채용/퇴직
- 인수 및 합병
예시 질의
- “최근 OpenAI가 무엇을 하고 있나요?”
- “어떤 경쟁자들이 가장 많은 뉴스를 만들고 있나요?”
- “모든 파트너십 발표 찾기”
- “이번 주 가장 중요한 경쟁 움직임은 무엇인가요?”
Prerequisites
- PostgreSQL (로컬 설치 또는 클라우드 서비스)
- Python 3.11+ (CocoIndex에 필요)
- API 키 (필수):
- Tavily API 키 (무료 티어: 하루 1,000 요청)
- OpenAI / OpenRouter API 키 (LLM 추출용)
Built With
- CocoIndex – 현대적인 데이터 파이프라인 프레임워크
- Tavily AI Search – AI 기반 검색 엔진
- OpenRouter – 다중 모델 API 게이트웨이
기여하기
질문이 있거나 기여하고 싶으신가요? 아래에 댓글을 남기거나 GitHub에서 이슈를 열어 주세요!
License: MIT
Repository: