Wikipedia 실시간 감시 로컬 AI 에이전트
- •KDnuggets가 API 키 없이 Ollama로 Wikipedia 실시간 편집을 감시하는 로컬 에이전트를 구축했다
- •설계는 저비용 Python 필터를 먼저 거치고, 임계값 이후에만 로컬 LLM을 호출하는 2단계 퍼널을 쓴다
- •에이전트는 원시 추론 조각을 스트리밍한 뒤 severity 1~5의 검증된 AgentVerdict JSON을 반환한다
KDnuggets는 2026년 8월 13일 Wikipedia의 공개 실시간 편집 피드를 감시하고 자체 추론을 클라이언트에 스트리밍하는 로컬 AI 에이전트 구축 가이드를 공개했다. 이 에이전트는 사용자 기기에서 Ollama를 통해 실행되며, API 키나 클라우드 계정이 필요 없고 외부 네트워크 연결은 Wikipedia의 공개 EventStreams 엔드포인트로만 나간다. 가이드는 "streaming"을 2가지 의미로 정의했다. 하나는 들어오는 즉시 실시간 이벤트를 소비하는 방식이고, 다른 하나는 완성된 답변을 기다리지 않고 에이전트 출력을 토큰 단위로 보여주는 방식이다.
구축 방식은 사람이 입력한 요청이 아니라 이벤트가 소프트웨어를 깨우는 ambient agent 패턴을 사용한다. LangChain은 이 개념의 프레이밍으로 언급됐고, 구글의 Agent Development Kit은 유사한 인프라 관점으로 제시됐다. 즉 에이전트는 request-response 호출이 아니라 스트림에 도착한 항목에 의해 깨어난다. 명시된 사전 조건은 Python 3.11 이상, `ollama pull llama3.1:8b` 또는 구조화된 JSON 출력을 지원하는 다른 모델을 갖춘 로컬 Ollama, 그리고 `pip install fastapi uvicorn httpx pydantic ollama sse-starlette`다.
핵심 설계는 2단계 퍼널이다. Wikipedia 편집 스트림은 활발한 날 모든 언어판을 합쳐 초당 여러 건의 편집을 밀어낼 수 있기 때문이다. Stage 1은 모든 이벤트에 대해 일반 Python 검사만 수행하며, 편집이 제거한 바이트 수와 사용자가 최근 몇 분 동안 만든 편집 수를 확인한다. Stage 2는 Stage 1 임계값을 넘은 더 작은 이벤트 집합에 대해서만 로컬 LLM을 깨운다. 이에 따라 로컬 컴퓨팅 사용을 보존하면서 에이전트가 실시간 스트림에 가깝게 머물도록 한다.
프로젝트 구조는 파이프라인을 `config.py`, `schemas.py`, `stream_source.py`, `filters.py`, `agent.py`, `broadcaster.py`, `main.py`, `tests/test_filters.py`로 나눈다. EventStreams 소비자는 열린 상태를 유지하는 일반 `GET` 요청으로 HTTP 위에서 Server-Sent Events(브라우저와 서버 간 단방향 업데이트)를 받는다. 빈 keep-alive 줄과 주석 줄은 무시하고, `data:` 페이로드를 JSON으로 파싱하며, 설정된 wiki만 필터링한 뒤 `HTTPError`가 발생하면 5초 대기 후 다시 연결한다.
가이드는 Wikipedia가 이 피드에서 명시적인 익명 사용자 플래그를 보내지 않는다고 설명한다. 익명 편집은 편집자의 IP 주소로 표시되므로 `is_anonymous_user`는 사용자명이 IPv4 또는 IPv6 형식과 일치하는지 확인한다. 파싱 헬퍼는 네트워크 의존성이 없는 순수 함수라서, 작성자는 실시간 피드에 연결하기 전에 현실적인 샘플 페이로드를 테스트할 수 있다.
Stage 1은 `EditVelocityTracker`를 사용한다. 이 구성요소는 사용자별 deque에 각 사용자의 최근 편집 타임스탬프를 저장하고, 뒤따르는 시간 창 밖의 이벤트를 잘라낸다. 이에 따라 "2분 안에 5 edits" 같은 검사가 계속 정확하게 유지된다. `max_tracked` 보호 장치는 오래된 사용자를 제거해 멈추지 않는 스트림에서 딕셔너리가 끝없이 커지지 않게 하며, `Stage1Filter.evaluate`는 대부분의 이벤트에 `None`을 반환하고 바이트 제거 또는 편집 속도 임계값을 넘었을 때만 `FilterSignal`을 반환한다.
Stage 2는 Pydantic으로 `RecentChangeEvent`, `FilterSignal`, `AgentVerdict`를 정의한다. `AgentVerdict`에는 `is_likely_vandalism`, 1~5 범위의 `severity`, `reasoning`, `suggested_action`이 필요하다. 시스템 프롬프트는 모델에 편집이 vandalism처럼 보이는지, 또는 정당한 재작성·정리·병합인지 판단하라고 요구하며, 실제로 받은 숫자를 인용하도록 한다.
로컬 추론기는 `ollama.AsyncClient`를 호출하고, `format=AgentVerdict.model_json_schema()`를 사용하며, `stream=True`와 `temperature` 0.1을 설정한다. 가이드는 이 스키마 강제가 완료된 모델 응답을 `AgentVerdict`와 일치하는 유효한 JSON으로 만든다고 설명한다. 생성이 진행되는 동안 `evaluate_signal`은 실시간 표시를 위해 원시 문자열 조각을 yield하고, 이후 전체 텍스트를 `AgentVerdict.model_validate_json(full_text)`로 검증한 뒤 최종 typed verdict를 yield한다.
브로드캐스터는 연결된 각 클라이언트에 기본 `max_queue_size` 100의 개별 `asyncio.Queue`를 제공한다. `publish`는 `json.dumps`로 페이로드를 직렬화하고 `put_nowait`으로 각 구독자에게 보낸다. 큐가 가득 차면 처리 루프를 막는 대신 해당 클라이언트가 메시지를 놓친다. 가이드는 이 방식이 느린 브라우저 탭 1개 때문에 실시간 Wikipedia 편집을 처리하는 에이전트가 멈추는 일을 막는다고 설명한다.