惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Engineering at Meta
Engineering at Meta
人人都是产品经理
人人都是产品经理
大猫的无限游戏
大猫的无限游戏
博客园 - 三生石上(FineUI控件)
量子位
腾讯CDC
The Cloudflare Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
云风的 BLOG
云风的 BLOG
Vercel News
Vercel News
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
L
LangChain Blog
aimingoo的专栏
aimingoo的专栏
The Hacker News
The Hacker News
T
The Exploit Database - CXSecurity.com
B
Blog
S
SegmentFault 最新的问题
P
Privacy & Cybersecurity Law Blog
T
Threatpost
博客园 - 聂微东
T
Tailwind CSS Blog
The Last Watchdog
The Last Watchdog
C
Check Point Blog
N
Netflix TechBlog - Medium
D
DataBreaches.Net
爱范儿
爱范儿
IT之家
IT之家
S
Secure Thoughts
M
MIT News - Artificial intelligence
NISL@THU
NISL@THU
C
Cisco Blogs
TaoSecurity Blog
TaoSecurity Blog
有赞技术团队
有赞技术团队
A
Arctic Wolf
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
P
Proofpoint News Feed
Spread Privacy
Spread Privacy
Schneier on Security
Schneier on Security
Simon Willison's Weblog
Simon Willison's Weblog
G
GRAHAM CLULEY
雷峰网
雷峰网
Project Zero
Project Zero
博客园 - Franky
H
Heimdal Security Blog
A
About on SuperTechFans
Security Latest
Security Latest
Webroot Blog
Webroot Blog
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Hugging Face - Blog
Hugging Face - Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More

Все публикации подряд на Хабре

Ловим музу за клавиатуру: как айтишнику стать автором Что умеет Midjourney в 2026? Мой немного грустный разбор этого шикарного инструмента Никто не любит писать тесты, но ИИ может исправить это IPv8 выглядит как мечта. Поэтому почти наверняка не взлетит Производители вернули в продажу материнки с DDR3. Что происходит? Управление агентом с телефона через Telegram теперь в KodaCode От координации к лидерству: как меняется роль руководителя разработки Я сделала родителям бизнес вместо пенсии: зарабатываем 70 тысяч, мама не даёт продать В три раза быстрее приемка товара и оптимизация трудозатрат на 73%: как «РСТ-Инвент» помог Gulliver Group ИИ-шечный мир победил? О влиянии искусственного интеллекта на игропром Кремль снижает давление на Телеграмм пока Европа строит интернет по паспорту Как CEO, CTO и CIO за 8 часов собрали ИИ-директора, который умеет держать позицию под давлением Как (не) потерять домен за выходные Вместо 8 разных VPS: как я организовал практику студентам на одном сервере Почему твой Open Source проект не замечают? R&D: искусство управления неопределенностью в разработке AI-дефляция: вакансий для разработчиков больше, а рост зарплат — худший за 15 лет Мы отдали управление роботами OpenClaw. Что из этого вышло Галактический ID: система идентификации для всех форм разумной жизни Шесть основ бизнес-анализа: начинаем с вопроса «Кто в игре?» Код-ревью, в котором дело не в коде Данные переехали. Команда — нет Системной подход к сдаче OSWE в 2025 Почему комната управления реактором покрашена в цвет морской пены 4 YAML-файла вместо PySpark: как аналитикам строить пайплайны без разработчиков LLM-агент для поиска свободных доменов: автоматизируем подбор Когда, зачем и как правильно начинать новую сессию в Claude Code? Как я заставил нейросеть писать макросы для FreeCAD Анатомия ИИ‑агента для подбора персонала. От тысячи резюме к топ‑10 за минуты Опыт разработчика как экономика внимания Автономность как точка невозврата: кто будет субъектом в цифровом будущем Обучение ИИ в «диких» условиях: как рутинные действия превращаются в датасеты Как измерить LLM для задач кибербеза: обзор открытых бенчмарков Где хранить код? Сравнение GitHub, GitLab и Bitbucket Математика объясняет, почему нормальное распределение встречается повсюду Почему ваш FinOps не работает: 12 тезисов от практиков Как подписать проектную документацию УКЭП с использованием бесплатных лицензий Pilot Адаптивное администрирование Sigla Vision Я грузил уран в бочки, а потом 20 лет строил ИТ в атомной отрасли Чем позвонить с Эвереста? История и обзор спутниковой связи. Часть 2 Как языковая модель помогает контролировать качество инструктажей по охране труда в металлургии Как не передать на desktop свой IP в РКН Анатомия SAP Privileges: как устроено управление правами в macOS MoneyDev: Сказка про три главных слова Обновлённый токенизатор видео K-VAE 2.0 от Сбера Как сделать диспетчеризацию дома на 1284 квартиры почти бесплатно Как мы разогнали железную дорогу Мы дали агентам рутину. Теперь надо решить — что делать с освободившимся временем Токсичный контент, промпт-хакинг и защита ИИ — всё о Guardrails для LLM Умный город начинается с точного взгляда: как «Фалькон Тех» меняет пространство к лучшему Навайбкодил приложение для анализа графов Почему Дюну так интересно читать? Упрощаем работу с рутиной или как стать Гендальфом Белым Деконструкция Go: CPU, RAM и что там происходит. Go Assembler база. Часть 1.1 Какие профессии исчезнут из-за ИИ, а какие появятся? И что с этим делать Как мы построили IT-отдел, где хочется расти: архитектурные встречи, прозрачные метрики и книжные подарки Rufler: Делаем из Claude Code автономный рой через один YAML-конфиг Sing-box и белый список приложений Как построить надёжный обмен сообщениями в микросервисах: лучшие практики для enterprise OpenAI строит MLM-пирамиду, а McKinsey и Accenture помогают ей в этом Дом, который не построил Фишер (Часть 2) «Сверхзвуковой математик» против «Вдумчивого логиста»: битва алгоритмов 3D-упаковки Мультимодальные модели – грубый и дорогой инструмент Разговоры ничего не стоят. Код тоже Проверки физических лиц: с кого начнет ФНС Топ-10 бесплатных нейросетей для создания видео в 2026 году Первые слои кода: как наши решения сегодня определяют архитектуру ИИ на десятилетия Разработка нового статического анализатора: PVS-Studio JavaScript Поиск уязвимостей ПО: базовый минимум или роскошный максимум Почему оценка персонала не работает как инструмент управления Как мы разработали ИИ-ассистента и сократили рутину продуктовой команды на 50% Как я ушел из найма, нажарил косточек и продал на маркетплейсах на 168 млн в год Когда 1С:ERP уже внедрена, а нормального производственного плана всё ещё нет Как я сделал Claude мультимодальным, подключив к нему Qwen Omni Как приглашение на вакансию мечты превращается в атаку Infrastructure as Code: философия и лучшие практики IaC Тестируем Yandex Code Assistant на задаче, в которой нужно хранить секреты nxs-universal-chart v3.0: новое поколение универсального Helm-чарта Callback Injection: Техника, которая отправила Microsoft Defender в глухой нокаут «Все идеи на стол»: митап как способ вывести проект из тупика Сегодня я узнал нечто новое о GPU благодаря багу в своей игре Как заставить LLM ̶ ̶г̶а̶л̶л̶ю̶ ̶ эволюционировать Карта событий как фундамент аналитики: практический кейс для E-commerce Что выбрать для AI: x86, ARM или RISC-V? Дайджест железа за март Роль соматических мутаций в развитии аутоиммунных заболеваний: путь к избирательной терапии Mythos от Anthropic — тревожный сигнал для всех, а не только для банков Guardrails для LLM на Java: как приручить промпт‑инъекции и токсичные ответы Green-VLA: как мы собрали VLA-модель для реального антропоморфного робота и не потеряли обобщение Финансовая гонка вооружений: почему умные люди добровольно в ней участвуют Эра ИИ-агентов наступила: выбираем лучшего цифрового сотрудника # Практический опыт внедрения WinCC Redundancy на производственном предприятии Сделал MVP за 3 дня, а потом неделю прикручивал оплату. Оно того стоило? Физика против Маска: почему Starship V3 может оказаться ещё одной катастрофой Нефть Венесуэлы: крупнейшие запасы в мире, но не крупнейшая нефтяная держава JPA 4. Переосмысление Hibernate Почему зеркальная фотокамера Nikon D5 десятилетней давности идеально подошла для миссии «Артемида-2» Проект «Уровень-Спутник» или как мы сделали платформу для гидрологов «Замедлиться, чтобы ускориться»: почему ИИ повышает цену ошибок в требованиях и архитектуре Как с нуля поднять трафик IT-компании на 1657% при бюджете 55 тыс. и выжить Pixel-perfect Downsampling — идеальная отрисовка 50 миллионов точек без потерь
Ваш RAG не умеет думать. А мой умеет
rRenegat (RU · 2026-04-24 · via Все публикации подряд на Хабре

Уровень сложностиСредний

Время на прочтение8 мин

Охват и читатели15

Обзор

Привет, Хабр!

Базовые RAG-системы уже научились неплохо справляться с прямыми вопросами по тексту. Но только если ответ лежит в одном конкретном абзаце, а вопрос сформулирован почти так же, как сам исходный документ. Попробуйте заставить систему связать факты из трёх разных источников или сделать банальный логический вывод. В большинстве случаев результат будет неутешительным. А уж про поиск скрытых связей я даже спрашивать боюсь.

Сегодня рассмотрим open-source RAG-фреймворк HippoRAG 2. В сфере RAG главным преимуществом данного фреймворка является качество ответов, потому что принципы его работы основаны на реальном человеческом мозге. Давайте разберёмся, откуда он взялся, как устроен изнутри и как его запустить.


Принципы работы

Префикс «Hippo» в названии — это отсылка к гиппокампу, структуре мозга, которая отвечает за формирование и извлечение долговременных воспоминаний. 

Разработчики из Ohio State University взяли за основу теорию гиппокампального индексирования Тейлера и Дисченна. Согласно ей, мозг хранит не сами воспоминания целиком, а лишь некоторые связи между ними, и при запросе восстанавливает полную картину через цепочку ассоциаций. 

В архитектуре HippoRAG каждый компонент соответствует своему нейробиологическому аналогу:

  • LLM играет роль неокортекса. Отвечает за извлечение структурированных представлений из текста. 

  • Retrieval-энкодер берёт на себя функцию парагиппокампальных областей мозга, обнаруживая семантические связи. 

  • Knowledge граф вместе с алгоритмом PPR (Personalized PageRank) имитирует сам гиппокамп. Он хранит сеть знаний и фактов и умеет строить в ней ассоциативные цепочки при поиске.

В HippoRAG подобный механизм долговременной памяти позволяет выявить скрытые связи между фактами. Речь идёт о многошаговом рассуждении (multi-hop reasoning). Это процесс, при котором система последовательно сопоставляет факты из разных источников по контексту и выстраивает цепочку связей, чтобы ответить на абстрактный вопрос.

Маскот фреймворка :)

Маскот фреймворка :)

Факты внутри системы называются триплетами. Это структурированное представление знаний в виде «субъект — отношение — объект». 

К примеру:

  • (Оливер Бэдмен, является, политик).

    Или:

  •  (Монтебелло, часть округа, Рокленд Каунти).

За извлечение триплетов отвечает OpenIE (Open Information Extraction) с помощью LLM. При индексации фреймворк отправляет каждый чанк документа в языковую модель с инструкцией извлечь все структурированные утверждения в виде троек. Результаты кэшируются в openie_cache/, чтобы при повторном запуске не тратить токены снова.

Зачем это нужно? Потому что для многошагового вопроса вроде: «В каком округе родился политик, который…» — обычный RAG просто найдёт документ про политика и отдельно про округ, а связь не уловит. А HippoRAG 2 склеивает два триплета через общую сущность (политик → место рождения → округ). Это и есть так называемая «скрытая связь».

Из всех извлечённых триплетов строится knowledge граф. Не такой огромный, как в GraphRAG, а более компактный(HippoRAG на датасете MuSiQue использует около 9 млн токенов — против 115 млн у GraphRAG).

При загрузке документов помимо создания эмбеддингов для чанков проводится извлечение упомянутых триплетов. Из извлечённых фактов строится knowledge-граф. Соответственно, при ответе на вопрос используется как стандартный проход по эмбеддированным документам с косинусным подобием, так и ранжирование фактов по графу. В этот момент задействуется PPR алгоритм. PPR — это вариация PageRank, где вместо случайного блуждания по всему графу, релевантность узлов измеряется относительно конкретного набора начальных (seed) узлов.

Схема работы

Схема работы


Установка и первый запуск

Установить фреймворк можно через pip или клонировав репозиторий.

conda create -n hipporag python=3.10
conda activate hipporag
pip install hipporag

Далее — пара экспортов (API-ключи и пути к кэшу) из env:

export OPENAI_API_KEY="sk-..."
export HF_HOME="/путь/к/кэшу"

Допустим, у нас есть три документа:

from hipporag import HippoRAG

docs = [
    "Oliver Badman is a politician.",
    "Montebello is a part of Rockland County.",
    "Erik Hort's birthplace is Montebello."
]

hipporag = HippoRAG(
    save_dir="my_rag_memory",    # сюда упадёт всё: эмбеддинги, граф, кэш
    llm_model_name="gpt-4o-mini",    
    llm_api_key = OPENAI_API_KEY,
    llm_base_url = OPENAI_BASE_URL,
    embedding_model_name="nvidia/NV-Embed-v2",
    embedding_api_key = EMBEDDING_API_KEY,
    embedding_base_url = EMBEDDING_BASE_URL     
)

Кстати говоря, фреймворк позволяет переопределять base_url для работы с локальными серверами. То есть ничто не мешает поднять собственные FastAPI-серверы с локальными LLM и моделями эмбеддингов или в Google Colab, используя библиотеку transformers, и затем просто указать эндпоинты с их выводом в openai-совместимом формате.

Пример эмбеддинг-модели

Ниже — самописный FastAPI-сервер для эмбеддингов.

import torch
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from transformers import AutoTokenizer, AutoModel
from typing import List
import uvicorn

class EmbeddingRequest(BaseModel):
    input: List[str] | str          
    model: str                     
    encoding_format: str = "float"  

class EmbeddingResponse(BaseModel):
    object: str = "list"
    data: List[dict]
    model: str
    usage: dict

MODEL_NAME = "название вашей модели"  
device = "cuda" if torch.cuda.is_available() else "cpu"

tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME)
model = AutoModel.from_pretrained(MODEL_NAME).to(device)
model.eval()

def embed_texts(texts: List[str]) -> List[List[float]]:
    inputs = tokenizer(
        texts,
        padding=True,
        truncation=True,
        return_tensors="pt",
        max_length=512
    ).to(device)

    with torch.no_grad():
        outputs = model(**inputs)
        embeddings = outputs.last_hidden_state.mean(dim=1) 
    return embeddings.cpu().numpy().tolist()

app = FastAPI(title="Local Embedding Server (OpenAI-compatible)")

@app.get("/v1/models")
async def list_models():
    return {
        "object": "list",
        "data": [
            {
                "id": MODEL_NAME,
                "object": "model",
                "owned_by": "local",
                "permission": []
            }
        ]
    }

@app.post("/v1/embeddings")
async def create_embedding(request: EmbeddingRequest):
    texts = [request.input] if isinstance(request.input, str) else request.input

    if not texts:
        raise HTTPException(status_code=400, detail="Input text list is empty")

    try:
        embeddings = embed_texts(texts)
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Embedding failed: {str(e)}")

    response_data = []
    for idx, emb in enumerate(embeddings):
        response_data.append({
            "object": "embedding",
            "index": idx,
            "embedding": emb
        })

    return EmbeddingResponse(
        data=response_data,
        model=MODEL_NAME,
        usage={
            "prompt_tokens": sum(len(t) for t in texts),
            "total_tokens": sum(len(t) for t in texts)
        }
    )

if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8001)

Теперь этот сервер можно передать в embedding_base_url="http://localhost:8001/v1".

Более простой и производительный вариант — использовать SentenceTransformer. Сервер остаётся полностью совместимым с OpenAI API.

import asyncio
from contextlib import asynccontextmanager
from typing import List, Union

from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from sentence_transformers import SentenceTransformer
import uvicorn

class EmbeddingRequest(BaseModel):
    input: Union[str, List[str]]  
    model: str  
    encoding_format: str = "float"

class EmbeddingResponse(BaseModel):
    object: str = "list"
    data: List[dict]
    model: str
    usage: dict

@asynccontextmanager
async def lifespan(app: FastAPI):
    app.state.model = SentenceTransformer("intfloat/e5-large-v2", device="cuda")
    yield
    app.state.model = None

app = FastAPI(title="Local Embedding Server (OpenAI-compatible)", lifespan=lifespan)

@app.get("/v1/models")
async def list_models():
    return {
        "object": "list",
        "data": [
            {
                "id": "local-embedding-model",
                "object": "model",
                "owned_by": "local",
                "permission": []
            }
        ]
    }

@app.post("/v1/embeddings")
async def create_embedding(request: EmbeddingRequest):
    texts = [request.input] if isinstance(request.input, str) else request.input

    if not texts:
        raise HTTPException(status_code=400, detail="Input text list is empty")

    model: SentenceTransformer = app.state.model
    try:
        embeddings = model.encode(texts, normalize_embeddings=True)
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Embedding failed: {str(e)}")

    response_data = [
        {
            "object": "embedding",
            "index": idx,
            "embedding": emb.tolist()
        }
        for idx, emb in enumerate(embeddings)
    ]

    return EmbeddingResponse(
        data=response_data,
        model=request.model,
        usage={
            "prompt_tokens": sum(len(text.split()) for text in texts),
            "total_tokens": sum(len(text.split()) for text in texts)
        }
    )

if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8001)

Индексация документов

Индексация запускается одной командой:

hipporag.index(docs=docs)

Что происходит внутри? 

  • Документы режутся на чанки (стандартно — по предложениям).

  • Каждый чанк эмбеддится.

  • Одновременно LLM обрабатывает каждый чанк через OpenIE и извлекает из него все смысловые триплеты.

  • Триплеты превращаются в узлы и рёбра knowledge-графа.

  • Эмбеддинги узлов графа тоже вычисляются (чтобы потом искать похожие факты). 

Где хранится?

В папке my_rag_memory (которую мы передали в save_dir) создаётся структура: 

  • embeddings/ — плоские файлы с эмбеддингами чанков и узлов графа (обычно .npy или через faiss индекс). 

  • graph/ — сериализованный граф (узлы, рёбра, веса). 

  • openie_cache/ — результаты извлечения триплетов, чтобы при повторном запуске не жечь токены заново.

На данном этапе фреймворк хранит эмбеддинги в формате .parquet. Но ничего не мешает дописать совместимость с векторными БД, особенно в наше время.

Важный нюанс: если вы перезапускаете индекс с теми же документами, HippoRAG 2 не будет заново дёргать OpenIE и LLM, а проверит кэш по хешу текста. Так что за токены, хотя бы тут, можете не переживать.

Что возвращает каждая функция?

retrieve — поиск без генерации ответа:

results = hipporag.retrieve(
    queries=["What county is Erik Hort's birthplace a part of?"],
    num_to_retrieve=2
)
print(results)

На выходе — список списков. Для каждого запроса: 

[
    [ 
        {"text": "Montebello is a part of Rockland County.", "score": 0.92, "type": "chunk"},
        {"text": "Erik Hort's birthplace is Montebello.", "score": 0.87, "type": "chunk"}
    ]
]

Важный момент: type может быть "chunk" (найденный чанк) или "fact" (найденный триплет из графа) — зависит от того, что победило в ранжировании.

rag_qa — выполняет полный цикл: поиск → передача найденного контекста в LLM → генерация ответа

answers = hipporag.rag_qa(
    queries=["What county is Erik Hort's birthplace a part of?"]
)
print(answers)

Вернёт список строк с ответами, например: ["Rockland County"]. В ответе также возвращается список использованных чанков.

Оценка с gold-данными

Один из самых приятных моментов, это когда у вас есть золотые ответы и поддерживающие документы для оценки:

gold_answers = [["Rockland County"]]
gold_docs = [
    ["Montebello is a part of Rockland County.",
     "Erik Hort's birthplace is Montebello."]
]

eval_results = hipporag.rag_qa(
    queries=queries,
    gold_docs=gold_docs,
    gold_answers=gold_answers
)

Тогда в eval_results упадёт словарь с метриками: 

  • "retrieval_hit_rate" (попали ли нужные чанки в топ-N), 

  • "answer_accuracy" (точность ответа, часто через F1 или EM), 

  • "latency_seconds" — чтобы потом бенчмаркать.

Удаление и добавление документов

Если понадобится удалить документ, есть hipporag.delete_docs(doc_indices=[0,2]).

Граф перестраивается инкрементально, не с нуля. Для добавления новых данных вызывается hipporag.index(docs=new_docs). Система сама определит, что уже проиндексировано, а что нет.


Заключение

Признаюсь, я обожаю HippoRAG 2. Для меня это максимально удобный инструмент, который ещё и справляется лучше своих аналогов. Естественно, он не универсальная затычка для любой проблемы, но в задачах контекста, рассыпанного по множеству документов, ему нет равных.

Я советую обратить внимание на фреймворк уже за то, что авторам удалось решить задачу ассоциативного рассуждения без многократного роста стоимости запросов. Это ли не чудо?

© 2026 ООО «МТ ФИНАНС»