Сравнение API для извлечения научных данных: когда нужен полный текст, а когда метаданные. Практические примеры кода на Python.
Когда вы строите исследовательского агента, первое реальное решение — что возвращается из поиска: запись о статье или абзац, отвечающий на вопрос. Это разные продукты, и выбор неправильного аукнется через три недели в виде RAG-пайплайна, который вы не планировали строить.
Valyu — это поисковый и DeepResearch API, который возвращает полный текст со структурированными цитатами по академическим, клиническим, научным, патентным и регуляторным источникам.
Semantic Scholar — академическая поисковая система и API метаданных от Института ИИ Аллена.
Выбирайте Valyu, когда единица работы — фрагмент доказательства: поиск внутри статей в момент запроса, получение протокола клинического исследования и этикетки FDA вместе с литературой, цитируемый ответ или полный многошаговый отчет без собственного стека извлечения.
Выбирайте Semantic Scholar, когда единица работы — запись: поиск статей по теме, обход графа цитирований, ранжирование по влиятельности, профили авторов, рекомендации. Это бесплатно, корпус огромен, и никто другой не даст граф цитирований так чисто.
Короткая версия в коде:
# Valyu возвращает текст, отвечающий на вопрос, с прикрепленной цитатой
{
"title": "...",
"content": "In the phase 3 cohort (n=847), median PFS was...",
"citation": {
"doi": "10.1056/...",
"authors": [...],
"fragment": "#:~:text=median%20PFS"
}
}
# Semantic Scholar возвращает записи, которые вам нужно прочитать
{
"paperId": "649def34...",
"title": "...",
"abstract": "...",
"citationCount": 1893
}
Академический граф Semantic Scholar охватывает 214 миллионов статей, 2,49 миллиарда цитирований и 79 миллионов авторов. Покрытие включает все области, собранные из издательских лент, серверов препринтов и веб-краулинга.
API организован как три сервиса:
Полный текст здесь не является продуктом времени запроса. Он живет в S2ORC: более 8 миллионов полнотекстовых статей, вместе с 81 миллионом узлов статей и 73 миллионами аннотаций, распространяемых как массовая загрузка. Также есть конечная точка поиска по фрагментам для статей открытого доступа, которая возвращает короткие выдержки, а не фрагменты глубины поиска, которые обычно нужны RAG-пайплайну.
Итак: метаданные и аннотации во время запроса, полный текст как корпус, который вы размещаете сами.
Valyu полнотекстово индексирует примерно 4 миллиона статей открытого доступа, плюс лицензионный журнальный контент:
Полный корпус аннотаций PubMed из 37 миллионов записей доступен как опция через include_abstracts. Подробнее об этом флаге ниже, потому что это самая часто искажаемая деталь этого API.
Помимо литературы, индекс охватывает ClinicalTrials.gov (500K+ испытаний), этикетки лекарств FDA из DailyMed (150K+), документы SEC (3M+), патенты USPTO (8M+) и патенты EPO (6M+) с полным текстом и рисунками, плюс источники по геномике и химии. Один запрос может охватывать несколько источников одновременно, что важно, если вашему агенту нужно перейти от механизма в статье к испытанию, его тестирующему, и к этикетке одобренного препарата.
Оба выполняют поиск. Вот Semantic Scholar, переписанный из примера в документации в то, что вы бы реально встроили в агента, а не в интерактивный цикл подсказок:
import os
import requests
S2_BASE = "https://api.semanticscholar.org"
HEADERS = {"X-API-KEY": os.environ["S2_API_KEY"]}
def search_papers(query: str, limit: int = 10):
r = requests.get(
f"{S2_BASE}/graph/v1/paper/search",
headers=HEADERS,
params={
"query": query,
"limit": limit,
"fields": "title,abstract,year,citationCount,externalIds,url",
},
timeout=30,
)
r.raise_for_status()
return r.json().get("data", [])
def recommendations(paper_id: str, limit: int = 10):
r = requests.get(
f"{S2_BASE}/recommendations/v1/papers/forpaper/{paper_id}",
headers=HEADERS,
params={"fields": "title,year,citationCount,url", "limit": limit},
timeout=30,
)
r.raise_for_status()
return r.json()["recommendedPapers"]
for p in search_papers("chimeric antigen receptor T cell exhaustion"):
print(f"{p['citationCount']:>6} {p['year']} {p['title']}")
Параметр fields — это первое, что нужно изучить. Если ничего не запросить, вы получите почти ничего, и каждое дополнительное поле — это соединение на их стороне, так что держите список компактным.
Для всего, что превышает несколько тысяч результатов, используйте массовый поиск с его токеном продолжения вместо постраничного обхода конечной точки релевантности:
import json
import requests
url = "https://api.semanticscholar.org/graph/v1/paper/search/bulk"
params = {
"query": "(cold-temperature) | flu",
"fields": "title,year",
"year": "2023-",
}
retrieved = 0
with open("papers.jsonl", "a") as f:
while True:
r = requests.get(url, params=params, timeout=60).json()
for paper in r.get("data", []):
print(json.dumps(paper), file=f)
retrieved += len(r.get("data", []))
if "token" not in r:
break
params["token"] = r["token"]
print(f"Retrieved {retrieved} papers")
Обратите внимание на синтаксис запроса в массовой конечной точке: | — это ИЛИ, ведущий - отрицает, а скобки группируют. Это не тот же синтаксис, что в конечной точке поиска по релевантности, что часто сбивает с толку.
Valyu тоже выполняет поиск, но по меньшему полнотекстовому индексу:
import os
from valyu import Valyu
# Читает VALYU_API_KEY из окружения, если ключ не передан
valyu = Valyu(api_key=os.environ["VALYU_API_KEY"])
response = valyu.search(
"Phase 3 melanoma immunotherapy trials",
search_type="proprietary",
included_sources=["valyu/valyu-pubmed", "valyu/valyu-clinical-trials"],
max_num_results=15,
response_length="large", # полная методология и результаты, а не только аннотации
)
for result in response.results:
print(result.title, result.url)
# content может быть str | list | dict; структурированные источники возвращают объекты
print(result.content)
Есть TypeScript и Rust SDK, если Python не ваш стек, а REST-эндпоинты доступны, если вы не хотите добавлять зависимость.
Semantic Scholar. Чтобы искать внутри статей, вы скачиваете S2ORC, разбиваете на чанки, эмбедите, храните и запрашиваете собственный индекс. Это реальный пайплайн: объектное хранилище, задача эмбеддинга, векторная база данных и стратегия обновления при изменении корпуса. Вполне разумно, если вы хотите контролировать чанкинг и эмбеддинги, и это правильный выбор для некоторых команд. Но это не то, что вы получаете из API-вызова.
Valyu. Полный текст — это возвращаемое значение по умолчанию:
response = valyu.search(
"mechanisms of acquired resistance to KRAS G12C inhibitors",
search_type="proprietary",
included_sources=["valyu/valyu-pubmed"],
max_num_results=10,
response_length="large",
)
for r in response.results:
print(r.title)
print(r.content[:500]) # релевантные полнотекстовые фрагменты, а не аннотация
print(r.citation.doi, r.citation.fragment) # fragment делает глубокую ссылку на фрагмент
Поле fragment стоит выделить отдельно. Это текстовая фрагментная глубокая ссылка на точный цитируемый отрывок, так что рецензент может кликнуть на цитату в выводе вашего агента и попасть на предложение, а не на статью. Если кто-то когда-либо будет проверять утверждения вашего агента, это поле — разница между «проверяемо» и «поверьте мне на слово».
По умолчанию: поиск PubMed возвращает статьи, для которых доступен полный текст, давая аннотацию плюс наиболее релевантные фрагменты полного текста.
include_abstracts=true: расширяет поиск на полный корпус аннотаций PubMed из 37 миллионов записей, где статьи без полного текста возвращают только аннотацию.
Полнотекстовый поиск — это значение по умолчанию. Полный корпус аннотаций — это опция. Если вы читали противоположное, это ошибка.
# Глубокие доказательства, более узкая сеть (по умолчанию)
valyu.search(query, included_sources=["valyu/valyu-pubmed"])
# Широкая сеть, менее глубокие доказательства для статей без полного текста
valyu.search(query, included_sources=["valyu/valyu-pubmed"], include_abstracts=True)
Используйте значение по умолчанию для синтеза доказательств. Включайте флаг для обзора покрытия и скрининга в стиле систематического обзора, где пропустить статью хуже, чем иметь только аннотацию.
У Semantic Scholar нет конечной точки генерации ответов. Ai2 отдельно поставляет Ai2 Scholar QA: систему цитируемого синтеза с открытым исходным кодом на основе более 11 миллионов полнотекстовых статей и 100 миллионов аннотаций, доступную как Docker-приложение, асинхронный API или Python-пакет. Вы приносите свои ключи Semantic Scholar, Anthropic и OpenAI и размещаете её сами. Это хорошее программное обеспечение. Но это также инфраструктура, которую вы теперь эксплуатируете.
Valyu поставляет синтез как управляемую API-поверхность. Answer API возвращает цитируемый ответ одним вызовом. DeepResearch выполняет автономное многошаговое исследование: планирование, поиск, извлечение, проверку фактов и написание отчёта.
import os
from valyu import Valyu
valyu = Valyu(api_key=os.environ["VALYU_API_KEY"])
task = valyu.deepresearch.create(
query=(
"What is the current evidence that GLP-1 receptor agonists reduce "
"major adverse cardiovascular events in patients without diabetes? "
"Cover trial design, effect sizes, and where the evidence conflicts."
),
mode="standard",
search={
"search_type": "proprietary",
"included_sources": ["academic"], # arXiv, PubMed, bioRxiv/medRxiv, ChemRxiv
"start_date": "2021-01-01",
},
research_strategy=(
"Prioritise randomised controlled trials and systematic reviews over "
"observational studies. Separate primary endpoints from secondary and "
"post-hoc analyses. Flag any conflicting or null results explicitly."
),
report_format=(
"Structured review with: evidence summary table (trial, n, population, "
"endpoint, effect size, CI), narrative synthesis, conflicting findings, "
"and evidence gaps."
),
output_formats=["markdown", "pdf"],
)
result = valyu.deepresearch.wait(task.deepresearch_id)
if result.status == "completed":
print(result.output)
print("cost:", result.cost)
for s in result.sources:
print(f"{s.title} | {s.doi or s.url}{s.fragment or ''}")
research_strategy и report_format — это два параметра, которые делают больше всего работы. Именно здесь вы кодируете методологию, которую применил бы эксперт в предметной области, и это разница между отчётом, который можно передать человеку, и стеной суммаризованных аннотаций.
Направьте его на один набор данных, когда точно знаете, где находятся доказательства, и попросите электронную таблицу вместо прозы:
task = valyu.deepresearch.create(
query=(
"Summarise reported mechanisms of acquired resistance to KRAS G12C "
"inhibitors in non-small-cell lung cancer, with supporting evidence "
"for each mechanism."
),
mode="fast",
search={
"search_type": "proprietary",
"included_sources": ["valyu/valyu-pubmed"],
"start_date": "2022-01-01",
},
deliverables=["xlsx"], # таблица механизм-доказательство
tools={"code_execution": True}, # требуется для xlsx/pptx/docx
)
DeepResearch также поддерживает вебхуки и контрольные точки с участием человека, что вам нужно, когда вы не хотите, чтобы агент публиковал отчёт без проверки.
Определите единицу работы вашего агента. Если это фрагмент доказательства — берите Valyu. Если это запись — Semantic Scholar. Скачайте SDK (или используйте REST) и напишите скрипт, который по вашему реальному запросу выведет первые 5 результатов с обоих API. Сравните, что ближе к вашему сценарию. Через 30 минут у вас будет ответ, какой API интегрировать.
Хочешь закрепить знания на практике?
Решай задачи на Algolit — интерактивная платформа для обучения
Начать бесплатно →