ai-graph-crawler
Перетворює будь-який сайт на граф знань, з яким уміють працювати LLM-агенти — і люди.
ai-graph-crawler (agc) — AI-надбудова над ядром graph-crawler. Ядро будує граф сайту
(сторінки = ноди, посилання = ребра); agc додає пошук по графу, автономних агентів, детерміновану
екстракцію за схемою/рецептом, MCP-сервер для Claude Code / Cursor, моніторинг змін, контроль вартості
LLM і чесну політику збору даних у вебі 2026 року.
pip install "ai-graph-crawler[openai,api,mcp]"
agc adaptive https://example.com "python developer kyiv" --prefer-native --respect-policy --out site.json
agc mcp site.json --tools graph.search,graph.excerpts,graph.page # → інструмент для Claude Code
Навіщо
Веб 2026 року — не для скрейперів «зняв HTML → відрегекспив». Сайти публікують llms.txt, віддають
Markdown за Accept: text/markdown, декларують умови для AI-ботів у robots / Content-Signal / TDMRep / RSL,
беруть плату через HTTP 402. Агенти платять за токени, а LLM галюцинують на невалідованих даних.
agc побудований навколо трьох тез:
- Граф, а не список сторінок. Структура сайту — це сигнал: де каталог, де картки, де «сироти», що змінилось із минулого краулу, які сутності пов'язані.
- Спершу нативний канал, потім HTML, потім браузер. Дешевше, швидше, менше токенів, поважає волю сайту.
- Кожен факт має провенанс і ціну. Звідки взято, яким каналом, за якою політикою, скільки коштувало.
Можливості
Розумний краул
- Adaptive stop —
adaptive_crawl(url, query)краулить, доки метрики coverage / consistency / saturation для теми не дозріють, і зупиняється сам. Жодних «max_pages=1000 і сподіваємось». - ChannelSelector — для кожного URL пробує канали в порядку
llms.txt→Accept: text/markdown→ JSON-LD → API → XHR → HTML → browser. Профіль домену кешується 24 години. - PolicyGate — robots для AI-агентів (
GPTBot,ClaudeBot,*),Content-Signal, TDMRep well-known, RSLLicense:, HTTP 402crawler-price→pay | skip | alternative. Заборонені URL не потрапляють у чергу, рішення пишеться в провенанс кожної ноди. - LiveCrawlAgent — LLM-агент сам вирішує, куди йти далі й коли зупинитись, під бюджетом токенів.
- Stop-conditions ядра через
control_channel, події прогресу (CrawlEvent) для WebSocket-клієнтів.
Пошук і RAG
- GraphIndex — BM25, векторний, гібридний (RRF) пошук по всьому графу;
excerpts()повертає релевантні фрагменти, а не сторінки цілком;map()— перелік URL за темою. - Real-time індекс під час краулу (
LiveIndexPlugin), інкрементальнийupsert/sync. - Персистентні вектори з ключем
node_id:content_hash:SqliteVectorStore(0 залежностей),FaissVectorStore,ChromaVectorStore,QdrantVectorStore,PGVectorStore— незмінені сторінки не переембеддяться. - Канонічний Markdown ноди через
html2md-clean, heading-aware чанкінг з overlap і semantic breakpoints, експорт у JSONL / LangChain / LlamaIndex або прямий інжест у векторну БД (agc export --to qdrant://…).
Екстракція даних
- CssExtractor / XPath за JSON-портативною
ExtractionSchema— детерміновано, без LLM. - ExtractionRecipe — версійований JSON/YAML-рецепт (селектори, XHR, post-process, приклади),
який компілюється в standalone Python, перевіряється в sandbox і лікується сам при зміні верстки
(
DriftDetector→RecipeHealer→ евали на held-out → shadow → promote). Детально —docs/RECIPE.md. - LLMExtractionPlugin — схемна екстракція з чанкінгом довгих сторінок і merge; BatchLLMExtractor —
3–5 сторінок в одному промпті зі стабільним
cache_prefix, нижчий$/сторінку; DeterministicExtractor — LLM один раз виводить CSS-схему для домену, далі екстракція безкоштовна. - EvalSuite — golden-набори, verbatim-докази (галюцинація / пропуск), consistency між прогонами, gate проти baseline — рецепт не промоутиться, якщо став гіршим.
- ParserCodegenAgent — коли потрібен саме код: LLM бачить фінальний HTML і network-лог браузера (XHR-ендпойнти), пише парсер і сам себе виправляє за stderr із sandbox.
Для агентів (agent-native)
- MCP-сервер
agc mcp site.json— інструментиgraph_search,graph_excerpts,graph_map,graph_page,graph_extract,graph_entities,agent_search… зbudgetу кожному виклику йCostSnapshotу_meta; ресурсиgraph://{alias}/report|map|pages/{id}з адреснимиnotifications/resources/updated; read-only типово;--print-config→ готовий.mcp.json. Гайд —docs/mcp/claude-code.md. - REST API
/v1(FastAPI): graphs · tools · search · map · extract · scrape · jobs (WS-прогрес) · monitors. - Site-as-API — рецепт стає OpenAPI-роутером;
/.well-known/agc.jsonі/.well-known/agent-card.jsonдозволяють агентам самим знайти, що вміє ваш сервер. - Ізоляція від prompt injection —
InjectionGuardвирізає інструкції для моделі з веб-контенту;ReaderLLMчитає недовірений текст у межахwrap_untrusted,PlannerLLMбачить лише структуровані підсумки й ходить тільки поAllowListдоменів;LiveCrawlAgent(isolate_roles=True, allow_domains=[…]). - AskDataAgent — питання природною мовою до таблиці записів («яка середня зарплата по містах?»):
LLM повертає лише
QueryPlan(whitelist фільтрів / group-by / агрегатів, безeval), план виконується детерміновано, кожен рядок відповіді з провенансом.
Локальні моделі та vision
- Дистиляція в SLM —
distill.build_dataset(graph, recipe=)→ chat-JSONL для fine-tune (OpenAI / Ollama / vLLM),slm_from_env()підключає локальну модель якTieredLLM.cheap,evaluate_slm()міряє точність полів. - Vision-канал —
VisionProbe(vlm, screenshot=): скріншот → VLM (OpenAIVisionабо Ollamallava/qwen2-vl) → Markdown; останній канал уChannelSelector, вмикається явно, провенансchannel == "vision".
Живий двійник сайту
- Monitor — підписка
{url, pattern, query, schema, webhook, interval}→ рескан →diff_graphs→ LLM-суддя «чи важлива зміна для query» → підписаний webhooksite.changed(HMAC-SHA256, Stripe-стиль). - Шина змін —
ChangeEvent{severity, matters, why, field_changes, section_changes}з детермінованимscore_change(правка дати чи лічильника — severity 0.05, відсікаєтьсяmin_severity);EventBusфан-аутить живим WS-клієнтам/v1/ws/events,EventLogзберігає append-only JSONL з replaysince=seq,WebhookSinkретраїть з backoff, ідемпотентністюX-AGC-Event-Idі HMAC-підписомpage.changed. - Пріоритет рескану —
Monitor.plan(sub_id, budget_pages=):ChangePredictorза історією змін каже, які URL рескaнити першими;Subscription(budget_pages=)— інкрементальний рескан лише цих сторінок. - Колекції «Websets» —
CollectionStore: збережений пошук/патерн з матеріалізованим станом (added / removed / changed), MCP-ресурсиgraph://{alias}/collections[/{id}]з авто-refresh, REST/v1/collections.
Дані для людини
agc report site.json --out report.md --html report.html --llms-txt llms.txt— паспорт краулу, зміст сайту, таблиця записів, матриця покриття полів, таймлайн, фасети, іменний покажчик сутностей, картки сторінок — один самодостатній файл без CDN, кожен факт із провенансом.agc diff yesterday.json today.json— що з'явилось, змінилось, зникло; diff heading-секцій і полів.agc classify | cluster | entities | kg— тип сторінки, кластери тем, сутності (люди, організації, ціни, дати, контакти), knowledge graph із 3-шаровою дедуплікацією (exact → fuzzy → LLM-арбітр).
Економіка LLM
- CostLedger / TokenBudget — ліміти на виклики, токени й долари; таблиця цін моделей
(перевизначається
AGC_PRICING_JSON), звіт «$ за правильний запис». - TieredLLM — дешева модель першою, сильна лише за низької
confidence, частка ескалацій обмежена. - Prompt caching через
cache_prefix, облік кешованих токенів. - Провайдери: OpenAI (і сумісні: Azure, OpenRouter, vLLM, Ollama), Anthropic, AWS Bedrock, Emergent Universal Key.
FakeLLM/CassetteLLM(record → replay) для детермінованих тестів без ключів.
Швидкий старт
pip install "ai-graph-crawler[openai,api,mcp]" # ядро graph-crawler>=5.3.2 ставиться залежністю
export OPENAI_API_KEY=... # або GEMINI_API_KEY / ANTHROPIC_API_KEY / AWS creds / EMERGENT_LLM_KEY
60 секунд у Python
import asyncio
from ai_graph_crawler import (
ChannelSelector, GraphIndex, LiveCrawlAgent, TokenBudget,
adaptive_crawl, build_report, diff_graphs,
)
from ai_graph_crawler.crawl.policy import PolicyGate
from ai_graph_crawler.llm import llm_from_env
from graph_crawler import load_graph, save_graph
async def main():
# 1. Краул до насичення теми — нативні канали, чесна політика
graph, index, metrics = await adaptive_crawl(
"https://example.com", "python developer kyiv",
channels=ChannelSelector(), policy=PolicyGate(purpose="ai_input"), max_pages=200,
)
print(metrics.to_markdown())
save_graph(graph, "site.json")
# 2. Пошук по графу: гібрид BM25 + вектори, релевантні фрагменти
for hit in index.search("remote python vacancies", mode="hybrid", top_k=5):
print(hit.url, round(hit.score, 3))
for ex in index.excerpts("salary range", top_k=3):
print("…", ex.text[:120])
# 3. Агент під бюджетом — сам вирішує, куди йти
llm = llm_from_env()
TokenBudget(max_calls=30, max_usd=0.50).attach(llm)
result = await LiveCrawlAgent(llm, max_pages=40).explore("знайди всі сторінки вакансій", "https://example.com")
# 4. Звіт для людини і diff з минулим краулом
print(build_report(graph, index=index).to_markdown()[:2000])
print(diff_graphs(load_graph("yesterday.json"), graph).to_markdown())
asyncio.run(main())
60 секунд у CLI
agc adaptive https://example.com "python developer kyiv" --prefer-native --respect-policy --out site.json
agc search site.json "remote python" --mode hybrid --vector-store site.db
agc report site.json --out report.md --html report.html --records-csv records.csv
agc export site.json --to qdrant://localhost:6333?collection=site --prune
agc mcp site.json --tools graph.search,graph.excerpts,graph.page --print-config > .mcp.json
agc monitor add https://example.com/jobs --pattern "/jobs/" --query "нові вакансії Python" \
--webhook https://hooks.example/agc --secret s3cret --interval 3600 --check-now
agc monitor plan <id> # які URL рескaнити першими (ChangePredictor)
agc ask site.json "яка середня зарплата по містах?" # питання до таблиці записів, без eval
agc serve --recipe jobs.yaml --graph site.json --port 8080 # REST + WS + монітори + Site-as-API
Повний перелік: agc search | explore | codegen | adaptive | extract | evals | drift | heal | report | coverage |
timeline | facets | classify | cluster | entities | kg | diff | export | ask | distill | collections | serve | mcp | monitor.
Типові сценарії з кодом і порівнянням з альтернативами — docs/USE_CASES.md.
Як це влаштовано
┌──────────────────────── ai-graph-crawler (agc) ────────────────────────┐
URL / query ──▶│ crawl/ ChannelSelector · PolicyGate · AdaptiveStop · AINode │
│ index/ GraphIndex (BM25 + vectors + RRF) · VectorStore backends │
│ extraction/ CssExtractor · LLMExtraction · DeterministicExtractor │
│ recipe/ ExtractionRecipe · EvalSuite · Drift · Heal · Store │
│ agents/ GraphSearch · LiveCrawl · ParserCodegen · AskData · Roles │
│ analysis/ classify · cluster · entities · knowledge graph · diff │
│ present/ Report · PageCard · Coverage · Timeline · Facets · Terms │
│ serve/ MCP · REST /v1 · Jobs+WS · Monitor · ChangeEvents · Site-API│
│ distill/ датасет → chat-JSONL → локальна SLM як TieredLLM.cheap │
│ llm/ OpenAI · Anthropic · Bedrock · Emergent · Tiered · Retry │
└────────────────────────────────┬───────────────────────────────────────┘
│ плагіни ядра (ON_BEFORE_SCAN / ON_AFTER_SCAN / …)
┌────────────────────────────────▼───────────────────────────────────────┐
│ graph-crawler 5.3 — граф сайту, драйвери (http / tls / playwright) │
└────────────────────────────────────────────────────────────────────────┘
Кожен модуль — самостійний і підключається до ядра як плагін; усе, що потребує мережі чи LLM,
має офлайн-двійника для тестів (FakeLLM, CassetteLLM).
Порівняння з альтернативами
Оцінка станом на середину 2026 року; ✅ є · ◐ частково / через зовнішні інструменти · — немає.
| Можливість | agc | Crawl4AI | Firecrawl | Scrapy + LLM |
|---|---|---|---|---|
| Граф сайту як первинна структура (ребра, глибина, сироти, кластери) | ✅ | — | ◐ (/map) |
— |
| Adaptive stop за метриками теми (coverage / consistency / saturation) | ✅ | ◐ | — | — |
Нативні канали перед HTML (llms.txt, Accept: text/markdown, JSON-LD, API) |
✅ | — | ◐ | — |
| Політика збору для AI-ботів (robots AI-UA, Content-Signal, TDMRep, RSL, HTTP 402) | ✅ | — | ◐ | ◐ (robots) |
| BM25 + векторний + гібридний пошук по всьому краулу, персистентні вектори | ✅ | ◐ | ◐ (search) | — |
| Детермінована екстракція без LLM (CSS/XPath-схема) | ✅ | ✅ | ◐ | ✅ |
| Версійовані рецепти + евали + self-healing при зміні верстки | ✅ | — | — | — |
| Кодогенерація парсера з network-логом браузера і sandbox | ✅ | ◐ | — | — |
MCP-сервер з бюджетами, CostSnapshot і live-оновленням ресурсів |
✅ | ◐ | ◐ | — |
Site-as-API: рецепт → OpenAPI + /.well-known/agc.json / agent-card |
✅ | — | — | — |
| Моніторинг змін: LLM-суддя, severity подій, предиктор рескану, підписані webhook-и з replay | ✅ | — | ◐ | — |
| Облік вартості LLM у $ і «$ за правильний запис», tiered-роутинг моделей | ✅ | — | — | — |
| Ізоляція planner/reader від prompt injection | ✅ | — | — | — |
| Звіт для людини (Markdown/HTML/llms.txt) з провенансом кожного факту | ✅ | — | — | — |
| Знання/сутності: NER + knowledge graph з дедуплікацією | ✅ | — | ◐ | — |
Дистиляція у локальну SLM, vision-fallback, питання до даних без eval |
✅ | ◐ | — | — |
| Локально, open source, без хостованого сервісу | ✅ | ✅ | ◐ (self-host) | ✅ |
| Керований хостинг з масштабуванням | — | — | ✅ | — |
agc не намагається бути хостованим сервісом — це бібліотека й CLI, які ви запускаєте у своєму процесі,
контейнері або як MCP-сервер поруч зі своїм агентом.
Конфігурація
| Змінна | Призначення |
|---|---|
AGC_LLM |
openai | anthropic | bedrock | gemini | emergent; без неї — авто-детект за ключами OPENAI_API_KEY → ANTHROPIC_API_KEY → AWS creds → GEMINI_API_KEY → EMERGENT_LLM_KEY |
GEMINI_MODEL |
модель Gemini (типово gemini-3.5-flash; дешевше — gemini-3.5-flash-lite) |
AGC_LOG_LEVEL |
рівень логів CLI (типово WARNING) |
OPENAI_MODEL / ANTHROPIC_MODEL / BEDROCK_MODEL / EMERGENT_PROVIDER+EMERGENT_MODEL |
модель провайдера (типово gpt-4o-mini, claude-haiku-4-5, eu.amazon.nova-lite-v1:0, openai/gpt-4o-mini); для gpt-5*/o* автоматично використовуються max_completion_tokens без temperature |
OPENAI_BASE_URL |
OpenAI-сумісні бекенди: Azure, OpenRouter, vLLM, Ollama |
AGC_PRICING_JSON |
шлях або inline JSON із цінами моделей для CostLedger |
AGC_STATE_DIR |
стан моніторів (monitors.json, знімки графів); типово .agc |
AGC_CACHE_DIR |
профілі доменів і політики; типово ~/.cache/agc |
AGC_SCHEMA_CACHE |
кеш схем DeterministicExtractor |
Extras: [openai] [anthropic] [bedrock] [gemini] [emergent] [dates] [pandas] [embeddings] [faiss] [chroma] [qdrant] [pgvector] [xpath] [api] [mcp] [playwright] [all] [dev].
Docker
docker compose up agc-api # REST на :8080, стан і кеш — у volume /data
docker compose run --rm agc-report # разовий звіт по ./graphs/site.json
Документація
| Документ | Про що |
|---|---|
docs/USE_CASES.md |
12 типових сценаріїв з кодом, CLI і порівнянням з альтернативами |
docs/RECIPE.md |
ExtractionRecipe: модель, API, приклад JSON, roadmap |
docs/mcp/claude-code.md |
Підключення до Claude Code / Cursor / Claude Desktop, контракт інструментів, live-ресурси |
Ліцензія
MIT.
Metadata
Release files for ai-graph-crawler 0.9.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| ai_graph_crawler-0.9.2.tar.gz | 335.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| ai_graph_crawler-0.9.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 752.4 kB
Release files / ai_graph_crawler-0.9.2.tar.gz
| Download URL | ai_graph_crawler-0.9.2.tar.gz |
|---|---|
| Size | 335.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
90dd15fcb33735ef1363c85d84117259109b986785bc25db4424d98263005442
|
|
BLAKE2b-256 checksum How to use checksums |
169d74619935d6dc2edf521d7778a3793dbdf7f229d5c24a74a109e7414b0c9d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.7
|
Release files / ai_graph_crawler-0.9.2-py3-none-any.whl
| Download URL | ai_graph_crawler-0.9.2-py3-none-any.whl |
|---|---|
| Size | 417.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
0e1da483973004315d6efe486632628b6130fecccba0a3324892b1f1f11d65ea
|
|
BLAKE2b-256 checksum How to use checksums |
fb4fab9ea9e0c77943f603d47f817c8308661d53ed59b377ea206007e5a11a98
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.7
|