Предлагаю ознакомится экспертной общественности с моим мини-фреймворком для разработки LLM-based приложений: core-kbt

Концепция проекта

Проект core-kbt (kbt - это аббревиатура от Knowledge Base Trajectory) - это мини-фреймворк для разработки LLM-based приложений и доменных баз знаний, с примерами доменных знаний из областей представления знаний, LLM и средств разработки.

Идею проекта можно представить с разных сторон:

  • сделать удобные средства разработки для LLM-based приложений

  • разработать и использовать подход, при котором оптимизировать промпты для задачи нужно через оптимизацию контекста, который вычисляется из базы знаний задачи (доменной базы знаний)

  • проект является вариантом развития идеи prompting-as-code.

Со стороны удобства разработки

Для практической разработки приложения, использующего LLM:

  • необходимо иметь четкую модель данных того, что нужно подавать LLM на вход и получать на выходе

  • удобные возможности создавать новые AI-функции с предсказуемыми свойствами

  • работать с schema-less данными, но с фиксацией как JSON-схемы, так и семантической-схемы (онтологии), когда это необходимо

  • удобно просматривать и модифицировать данные, которые являются контекстом для LLM-промптов

  • кешировать ответы от LLM

  • распараллеливать запросы к провайдерам LLM с контролируемым значением requests-per-second.

Со стороны представления знаний

Новые возможности, которые дают технологии GenAI, требуют новых подходов к представлению знаний и методов программирования.
LLM модели пропустили через универсальные алгоритмы большие объемы текстовой информации и следует ожидать, что внутреннее представление LLM модели о мире будет соответствовать тому как люди представляют знания. Самым близким к человеческому способом представления знаний является онтологическое представление. Поэтому следует ожидать, что именно онтологическое представление будет мостом между "миром представлений LLM" и человеческим представлением знаний, которое необходимо для эффективного решения практических задач.

Предлагается использовать следующий верхне-уровневый более-менее универсальный подход к решению задачи с помощью LLM:

  • разработать верхне-уровневую онтологию, которая должна удобна и понятна LLM и человеку

  • разработать типичные доменные онтологии, которые можно использовать для конкретных задач

  • решать задачу в следующей постановке: разделить информацию по задаче на следующие блоки (<я, как исследователь проблемы с помощью LLM, описываю ...>):

    • <что я знаю>: в виде базы знаний на основе онтологии

    • <что я хочу узнать>: в виде задачи в сущностях базы знаний

    • <что я хочу сгенерировать>: в виде задачи в сущностях базы знаний.

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

Для чего полезен фреймворк

  • AI-функции для быстрого создания и использования функций для обработки информации через LLM, со структурированным ответом

  • база данных для YAML/JSON-сущностей в файловом представлении: быстрый и удобный ввод данных для обработки через AI, удобное редактирование сущностей до и после AI обработки

  • если JSON-схемы для YAML/JSON-сущностей недостаточно, для углубления знания для решения задачи нужна последовательная разработка доменной онтологии для этой задачи: можно использовать готовую верхне-уровневую онтологию как базу для создания доменной онтологии

  • разработка траекторий доменных баз знаний: YAML/JSON-сущности и состояние базы знаний хранится как файлы в git, что делает удобным мутации значений сущностей базы знаний через git-бранчевание для дальнейшей оптимизации и поиска лучшего состояния базы знаний

  • можно настроить CI pipeline для git-репозитория с запуском сервера AI-функций: в результате получится удобный цикл разработки AI-функций и поддержки доменной базы знаний

  • персистентные процессы для удобной реализации логики обработки, планирования обработки, кеширования ответов от внешних сервисов и отладки.

Фичи фреймворка

  • AI-функция со структурированным ответом

    • каждой AI-функции соответствует папка c теймплейтом промпта и JSON-схема для ответа:

      • j2 теймплейт для промпта

      • требуемая JSON схема для ответа

    • есть evaluate метод для вызова AI-функции

    • есть серверное приложение для динамического web API для вызова любой AI-функции:

      • сервер авторизует все запросы по API-токену (секрету)

      • пример клиента

  • структурированное представление YAML/JSON-сущностей:

    • каждой сущности соответствует папка с элементами сущностей, представленными как файлы

    • для удобства редактирования, значение для поля сущности может подгружаться из файла

    • есть API для работы с сущностями

  • готовый вариант верхне-уровневой базовой онтологии небольшого размера, которая понятна LLM и человеку

Направления дальнейшего развития проекта

  • интеграция с Langfuse для traceability и оценки качества промптов

  • примеры оптимизации промптов через траекторию доменных баз знаний

  • разработка инструментов для проведения исследования в выбранной области на основе доменной онтологии

  • дополнение core AI-функций.

Начало работы

  1. задать значения переменных среды в .env файле, например для DeepSeek:

DEVELOPMENT=1
HOST=127.0.0.1
PORT=5000
PYTHONUTF8=1
PYTHONIOENCODING=utf8
OPENAI_BASE_URL=https://api.deepseek.com
OPENAI_MODEL=deepseek-chat
OPENAI_API_KEY=<API_TOKEN>
AI_FUNC_API_TOKEN=<API_TOKEN>
  1. запустить сервер AI-функций:

./runner.sh -s kbt-core/ai_function_server.py
  1. Допустим мы хотим узнать столицу России. Будем использовать готовую AI-функцию generate_what_is с промптом и JSON-схемой ответа. Вызываем AI-функцию с соответствующими входными параметрами context, qualifier и description:

source .env
curl -X PUT "http://127.0.0.1:5000/ai-func/generate_what_is" \
  -H "Api-Token: $AI_FUNC_API_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d "{
  \"context\": \"Geography\",
  \"qualifier\": \"capital (in a shortest form)\",
  \"description\": \"of Russia\"
}"

Ответ:

{
  "result": {
    "final_answer": "Moscow",
    "notes": "Moscow has been the capital since the 15th century, with a brief interruption during the time of the Russian Empire when the capital was moved to Saint Petersburg.",
    "proof": "Moscow is the capital of Russia as recognized by the Constitution of the Russian Federation and is the political, economic, and cultural center of the country."
  }
}

Также можно посмотреть README в репозитории с ссылками на ресурсы в репозитории: https://github.com/ady1981/core-kbt/blob/master/README.ru.md

Комментарии (6)


  1. afternao
    15.06.2025 17:24

    А можно на человечьем для чего эта штука и примеры использования - очень много текста - какие то умные слова, а хочется сначала кратко - тип вот для такой задачи, вот так и так использовать вот такой результат. А если хочешь подробнее, то уже в доку.


    1. asiver Автор
      15.06.2025 17:24

      Использование AI-функции решает проблему как структурировать ответ от LLM так, чтобы на выходе получить что-то ожидаемое, а не просто текст.
      Например, мы хотим, чтобы LLM ответила на вопрос "что есть <X-по-описанию-Y>?"
      Есть соответствующий пример AI-функция "generate_what_is" https://github.com/ady1981/core-kbt/blob/master/ai_functions/generate_what_is/prompt.md.j2
      Допустим нас интересует столица России.
      В промпте вопрос выглядит как `What is {{qualifier}} {{description}}?`, т.е. нужно подставить в qualifier = capital, в description= `of Russia`
      Также нужно задать контекст для промпта, например context=`Geography`
      1) задаем .env файл
      2) запускаем веб API для AI-функций:
      `./runner.sh -s kbt-core/ai_function_server.py`
      3) задаем значения в запрос и получаем ответ:

      AI_FUNC_API_TOKEN=<...> ### задать секрет с которым стартовал ai_function_server.py
      
      curl -X PUT "http://127.0.0.1:5000/ai-func/generate_what_is" \
        -H "Api-Token: $AI_FUNC_API_TOKEN" \
        -H "Content-Type: application/json" \
        -H "Accept: application/json" \
        -d "{
        \"context\": \"Geography\",
        \"qualifier\": \"capital\",
        \"description\": \"of Russia\"
      }"
      {
        "result": {
          "final_answer": "Moscow",
          "notes": "Moscow has been the capital of Russia in its various forms (e.g., Tsardom of Russia, Soviet Union) for most of its history since the 15th century, with brief interruptions.",
          "proof": "Moscow is the capital of Russia as recognized by the Constitution of the Russian Federation and is the political, economic, and cultural center of the country. It is also the location of the Kremlin, the official residence of the President of Russia."
        }
      }



      1. vkrasikov
        15.06.2025 17:24

        А разве нельзя просто попросить LLM выдать ответ в желаемом формате, предоставив ей образец?


        1. asiver Автор
          15.06.2025 17:24

          Да, можно в промпте задать JSON-схему и примеры, это так и работает


  1. metheoryt
    15.06.2025 17:24

    Бро, для схем данных есть pydantic AI, для агентов и заданий вон, marvin ai или что там сейчас еще популярно. Чем этот проект отличается от них?


    1. asiver Автор
      15.06.2025 17:24

      Через pydantic AI можно задать prompt-теймплейт, ожидаемую JSON-schema ответа и получить работающую AI-функцию, которую можно вызывать по web API?
      Для качественной AI-функции нужно задать few-shots примеры и правила. Как это удобно сделать в pydantic AI?
      Вопросы о представлении и углубления знаний в pydantic AI не ставятся и не решаются, насколько можно судить. Вопросы по оптимизации качества AI-функции через оптимизацию контекста тоже не ставятся.