graph-tool-call
graph-tool-call
LLM-агенты не могут вместить тысячи определений инструментов в контекст. Векторный поиск находит похожие инструменты, но упускает рабочий процесс, к которому они принадлежат. graph-tool-call строит граф инструментов и извлекает нужную цепочку — а не просто одно совпадение.
Без извлечения | graph-tool-call | |
248 инструментов (K8s API) | 12% точности | 82% точности |
1068 инструментов (полный API GitHub) | переполнение контекста | 78% Recall@5 |
Использование токенов | 8,192 ток | 1,699 ток (79% ↓) |
Измерено с qwen3:4b (4-бит) — полный бенчмарк
Зачем
LLM-агентам нужны инструменты. Но по мере роста количества инструментов возникают две проблемы:
Переполнение контекста — 248 эндпоинтов Kubernetes API = 8,192 токена определений инструментов. LLM «захлебывается», и точность падает до 12%.
Векторный поиск пропускает рабочие процессы — Поиск по запросу "отмени мой заказ" находит
cancelOrder, но реальный процесс выглядит так:listOrders → getOrder → cancelOrder → processRefund. Векторный поиск возвращает один инструмент; вам нужна цепочка.
graph-tool-call решает обе проблемы. Он моделирует связи между инструментами в виде графа, извлекает многошаговые рабочие процессы с помощью гибридного поиска (BM25 + обход графа + эмбеддинги + аннотации MCP) и сокращает использование токенов на 64–91%, сохраняя или улучшая точность.
Сценарий | Только векторный поиск | graph-tool-call |
"отмени мой заказ" | Возвращает |
|
"прочитать и сохранить файл" | Возвращает |
|
"удалить старые записи" | Возвращает любой инструмент с "delete" | Деструктивные инструменты ранжируются первыми через аннотации MCP |
"теперь отмени его" (после списка заказов) | Нет контекста из истории | Понижает приоритет использованных инструментов, повышает приоритет инструментов следующего шага |
Несколько Swagger-спецификаций с пересекающимися инструментами | Дубликаты инструментов в результатах | Автоматическая дедупликация между источниками |
1,200 API эндпоинтов | Медленно, шумные результаты | Категоризация + обход графа для точного извлечения |
Как это работает
OpenAPI / MCP / Python functions → Ingest → Build tool graph → Hybrid retrieve → AgentПример — Пользователь говорит: "отмени мой заказ и оформи возврат"
Векторный поиск находит cancelOrder. Но реальный рабочий процесс:
┌──────────┐
PRECEDES │listOrders│ PRECEDES
┌─────────┤ ├──────────┐
▼ └──────────┘ ▼
┌──────────┐ ┌───────────┐
│ getOrder │ │cancelOrder│
└──────────┘ └─────┬─────┘
│ COMPLEMENTARY
▼
┌──────────────┐
│processRefund │
└──────────────┘graph-tool-call возвращает всю цепочку, а не один инструмент. Извлечение объединяет четыре сигнала с помощью взвешенного Reciprocal Rank Fusion (wRRF):
BM25 — поиск по ключевым словам
Обход графа — расширение на основе связей (PRECEDES, REQUIRES, COMPLEMENTARY)
Сходство эмбеддингов — семантический поиск (опционально, любой провайдер)
Аннотации MCP — подсказки read-only / destructive / idempotent
Установка
Основной пакет имеет нулевые зависимости — только стандартная библиотека Python. Устанавливайте только то, что вам нужно:
pip install graph-tool-call # core (BM25 + graph) — no dependencies
pip install graph-tool-call[embedding] # + embedding, cross-encoder reranker
pip install graph-tool-call[openapi] # + YAML support for OpenAPI specs
pip install graph-tool-call[mcp] # + MCP server / proxy mode
pip install graph-tool-call[all] # everythingДоп. компонент | Устанавливает | Когда использовать |
| pyyaml | YAML OpenAPI спецификации |
| numpy | Семантический поиск (подключение к Ollama/OpenAI/vLLM) |
| numpy, sentence-transformers | Локальные модели sentence-transformers |
| rapidfuzz | Обнаружение дубликатов |
| langchain-core | Интеграция с LangChain |
| pyvis, networkx | Экспорт HTML-графа, GraphML |
| dash, dash-cytoscape | Интерактивная панель управления |
| ai-api-lint | Автоисправление плохих API спецификаций |
| mcp | Режим MCP-сервера / прокси |
Быстрый старт
Попробуйте за 30 секунд (без установки)
uvx graph-tool-call search "user authentication" \
--source https://petstore.swagger.io/v2/swagger.jsonQuery: "user authentication"
Source: https://petstore.swagger.io/v2/swagger.json (19 tools)
Results (5):
1. getUserByName — Get user by user name
2. deleteUser — Delete user
3. createUser — Create user
4. loginUser — Logs user into the system
5. updateUser — Updated userPython API
from graph_tool_call import ToolGraph
# Build a tool graph from the official Petstore API
tg = ToolGraph.from_url(
"https://petstore3.swagger.io/api/v3/openapi.json",
cache="petstore.json",
)
print(tg)
# → ToolGraph(tools=19, nodes=22, edges=100)
# Search for tools
tools = tg.retrieve("create a new pet", top_k=5)
for t in tools:
print(f"{t.name}: {t.description}")
# Search with workflow guidance
results = tg.retrieve_with_scores("process an order", top_k=5)
for r in results:
print(f"{r.tool.name} [{r.confidence}]")
for rel in r.relations:
print(f" → {rel.hint}")
# Execute an OpenAPI tool directly
result = tg.execute(
"addPet", {"name": "Buddy", "status": "available"},
base_url="https://petstore3.swagger.io/api/v3",
)Планирование рабочего процесса
plan_workflow() возвращает упорядоченные цепочки выполнения с предварительными условиями — сокращая количество запросов агента с 3-4 до 1.
plan = tg.plan_workflow("process a refund")
for step in plan.steps:
print(f"{step.order}. {step.tool.name} — {step.reason}")
# 1. getOrder — prerequisite for requestRefund
# 2. requestRefund — primary action
plan.save("refund_workflow.json")Редактируйте, параметризуйте и визуализируйте рабочие процессы — см. Руководство по прямому API.
Другие источники инструментов
# From an MCP server (HTTP JSON-RPC tools/list)
tg.ingest_mcp_server("https://mcp.example.com/mcp")
# From an MCP tool list (annotations preserved)
tg.ingest_mcp_tools(mcp_tools, server_name="filesystem")
# From Python callables (type hints + docstrings)
tg.ingest_functions([read_file, write_file])Аннотации MCP (readOnlyHint, destructiveHint, idempotentHint, openWorldHint) используются как сигналы для извлечения — намерение запроса классифицируется автоматически, и запросы на чтение отдают приоритет инструментам только для чтения, в то время как запросы на удаление отдают приоритет деструктивным инструментам.
Выберите свою интеграцию
graph-tool-call поставляется с несколькими шаблонами интеграции. Выберите тот, который соответствует вашему стеку:
Вы используете... | Шаблон | Выигрыш в токенах | Руководство |
Claude Code / Cursor / Windsurf | MCP Proxy (агрегация N MCP-серверов → 3 мета-инструмента) | ~1,200 ток/запрос | |
Любой MCP-совместимый клиент | MCP Server (один источник как MCP) | варьируется | |
LangChain / LangGraph (50+ инструментов) | Gateway tools (N инструментов → 2 мета-инструмента) | 92% | |
OpenAI / Anthropic SDK (существующий код) | Middleware (monkey-patch в 1 строку) | 76–91% | |
Прямой контроль над извлечением | Python API ( | варьируется |
MCP Proxy (наиболее распространенный)
Когда у вас много MCP-серверов, их имена инструментов накапливаются в каждом запросе LLM. Объедините их за одним сервером: 172 инструмента → 3 мета-инструмента.
# 1. Create ~/backends.json listing your MCP servers
# 2. Register the proxy with Claude Code
claude mcp add -s user tool-proxy -- \
uvx "graph-tool-call[mcp]" proxy --config ~/backends.jsonПолная настройка, режим проброса, удаленный транспорт → Руководство по MCP Proxy.
LangChain Gateway
from graph_tool_call.langchain import create_gateway_tools
# 62 tools from Slack, GitHub, Jira, MS365...
gateway = create_gateway_tools(all_tools, top_k=10)
# → [search_tools, call_tool] — only 2 tools in context
agent = create_react_agent(model=llm, tools=gateway)Сокращение токенов на 92% по сравнению с привязкой всех 62 инструментов. См. Руководство по LangChain для автофильтрации и ручных шаблонов.
SDK middleware
from graph_tool_call.middleware import patch_openai
patch_openai(client, graph=tg, top_k=5) # ← add this one line
# Existing code unchanged — 248 tools go in, only 5 relevant ones are sent
response = client.chat.completions.create(
model="gpt-4o",
tools=all_248_tools,
messages=messages,
)Также работает с Anthropic через patch_anthropic. См. Руководство по Middleware.
Бенчмарк
Два вопроса: (1) Выбирает ли LLM правильный инструмент, когда ей дают только извлеченное подмножество? (2) Ранжирует ли сам механизм извлечения правильные инструменты в топ K?
Набор данных | Инструменты | Базовая точность | graph-tool-call | Сокращение токенов |
Petstore | 19 | 100% | 95% (k=5) | 64% |
GitHub | 50 | 100% | 88% (k=5) | 88% |
Mixed MCP | 38 | 97% | 90% (k=5) | 83% |
Kubernetes core/v1 | 248 | 12% | 82% (k=5 + онтология) | 79% |
Ключевой вывод — при 248 инструментах базовая модель «падает» (переполнение контекста) до 12%, в то время как graph-tool-call восстанавливает точность до 82%. В меньших масштабах базовая модель уже сильна, поэтому ценность graph-tool-call заключается в экономии токенов без потери точности.
→ Полные результаты (конвейер / только извлечение / конкурентный анализ / масштаб 1068 / агент LangChain на 200 инструментов для GPT и Claude): docs/benchmarks.md
# Reproduce
python -m benchmarks.run_benchmark # retrieval only
python -m benchmarks.run_benchmark --mode pipeline -m qwen3:4b # full pipelineРасширенные возможности
Гибридный поиск на основе эмбеддингов
Добавьте семантический поиск поверх BM25 + графа. Тяжелые зависимости не нужны — подключайтесь к любому внешнему серверу эмбеддингов.
tg.enable_embedding("ollama/qwen3-embedding:0.6b") # Ollama (recommended)
tg.enable_embedding("openai/text-embedding-3-large") # OpenAI
tg.enable_embedding("vllm/Qwen/Qwen3-Embedding-0.6B") # vLLM
tg.enable_embedding("sentence-transformers/all-MiniLM-L6-v2") # local
tg.enable_embedding(lambda texts: my_embed_fn(texts)) # custom callableВеса перебалансируются автоматически. См. Справочник API для всех форматов провайдеров.
Настройка извлечения
tg.enable_reranker() # cross-encoder rerank
tg.enable_diversity(lambda_=0.7) # MMR diversity
tg.set_weights(keyword=0.2, graph=0.5, embedding=0.3, annotation=0.2)Извлечение с учетом истории
Передавайте ранее вызванные инструменты, чтобы понизить их приоритет и повысить приоритет кандидатов для следующего шага.
tools = tg.retrieve("now cancel it", history=["listOrders", "getOrder"])
# → [cancelOrder, processRefund, ...]Сохранение / загрузка (сохраняет эмбеддинги + веса)
tg.save("my_graph.json")
tg = ToolGraph.load("my_graph.json")
# Or use cache= in from_url() for automatic save/load
tg = ToolGraph.from_url(url, cache="my_graph.json")Онтология с поддержкой LLM
tg.auto_organize(llm="ollama/qwen2.5:7b")
tg.auto_organize(llm="litellm/claude-sonnet-4-20250514")
tg.auto_organize(llm=openai.OpenAI())Строит более богатые категории, отношения и ключевые слова для поиска. Поддерживает Ollama, клиенты OpenAI, litellm и любые вызываемые объекты. См. Справочник API.
Другие возможности
Возможность | API | Документация |
Обнаружение дубликатов в спецификациях |
| |
Обнаружение конфликтов |
| |
Операционный анализ |
| |
Интерактивная панель управления |
| |
Экспорт HTML / GraphML / Cypher |
| |
Автоисправление плохих OpenAPI спецификаций |
|
Документация
Документ | Описание |
Все команды CLI | |
Методы | |
MCP-сервер / прокси, LangChain, middleware, прямой API | |
Полные таблицы конвейера / извлечения / конкурентного анализа / масштаба | |
Обзор системы, уровни конвейера, модель данных | |
Дизайн алгоритма — нормализация, обнаружение зависимостей, онтология | |
Конкурентный анализ, данные о масштабируемости API | |
Процесс релиза, поток изменений |
Участие в разработке
Вклад приветствуется.
git clone https://github.com/SonAIengine/graph-tool-call.git
cd graph-tool-call
pip install poetry pre-commit
poetry install --with dev --all-extras
pre-commit install # auto-runs ruff on every commit
# Test, lint, benchmark
poetry run pytest -v
poetry run ruff check . && poetry run ruff format --check .
python -m benchmarks.run_benchmark -vЛицензия
Latest Blog Posts
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/SonAIengine/graph-tool-call'
If you have feedback or need assistance with the MCP directory API, please join our Discord server