Выбор локальной LLM модели. Публикация на сайт с чатом. agents.. agents. ai.. agents. ai. gpt.. agents. ai. gpt. JavaScript.. agents. ai. gpt. JavaScript. llm.. agents. ai. gpt. JavaScript. llm. ollama.. agents. ai. gpt. JavaScript. llm. ollama. openai.. agents. ai. gpt. JavaScript. llm. ollama. openai. python.. agents. ai. gpt. JavaScript. llm. ollama. openai. python. swarm.. agents. ai. gpt. JavaScript. llm. ollama. openai. python. swarm. TypeScript.. agents. ai. gpt. JavaScript. llm. ollama. openai. python. swarm. TypeScript. yandexgpt.. agents. ai. gpt. JavaScript. llm. ollama. openai. python. swarm. TypeScript. yandexgpt. искусственный интеллект.. agents. ai. gpt. JavaScript. llm. ollama. openai. python. swarm. TypeScript. yandexgpt. искусственный интеллект. Машинное обучение.

Исходный код, разобранный в данной статье, опубликован в этом репозитории

Для решения некоторых задач бизнес-требованием является запуск LLM модели локально на своём железе. Это связано с SJW цензурой, например, стандартный датасет для обучения Llama не позволяет вести консультации, носящие медицинский характер: рекомендовать лекарства, обсуждать носящую интимный характер медицинскую тайну с ИИ-терапевтом (см побочки антидепрессантов)

DeepSeek-R1 в опенсорсе, качество модели сомнительно

DeepSeek-R1 в опенсорсе, качество модели сомнительно

Так же, если модель не умеет вызывать инструменты, она не нужна: бессмысленно вести медицинскую консультацию, которая не закончится продажей фармокологического продукта. Ниже преведены протестированные модели, которые сочетают консистентный русский язык и возможность интеграции в сторонние сервисы

Обзор моделей

  • NVidia Nemotron Mini, https://ollama.com/library/nemotron-mini

    Цитата: This instruct model is optimized for roleplay, RAG QA, and function calling in English. It supports a context length of 4,096 tokens. This model is ready for commercial use.

    Плюсы

    1. Работает на видеокарте ноутбука с 4Гб памяти

    Позволяет пригласить стажера и, не засветив ключи openai, понять, а сможет ли он вообще в программирование

    2. Умеет говорить на русском языке

    Важный пункт, см фото про deepseek

    3. Вызывает инструменты

    Условно работает, но винована Ollama: Если отправить промпт-костыль. Однако, игнорирует required параметры инструментов: передает только те данные, в которых модель на 100% уверена

    4. Не многословен: датасет заточен для генерации минимальных ответов: Никаких “наверное” или “вы хотели бы уточнить?”

    Огромный плюс, если у вас есть опыт работы с моделью Gemini: она постоянно спамит текстом вида: Would you like me to, Okay, here’s a, Okay, this is a, This is likely

    Минусы

    1. Рекурсивно вызывает инструменты, неправильно реагируя на tool output.

    Решается сбросом переписки после вызова инструментов и заметками для модели в system prompt

    2. Игнорирует required параметры инструментов,

    При вызове метода добавления товара в корзину гарантировать получение имени товара может только анализ последнего сообщения пользователя руками

    3. Из-за немногословности крайне не замотивированно ведет переписку: развести модель на нужное действие можно только задавая наводящие вопросы

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

    4. Вызывает несуществующие инструменты

    Если текстовый промпт содержит просьбу оплатить заказ, модель вызовет checkout_tool даже, если был подключен только add_to_cart_tool

  • Saiga/YandexGPT, https://huggingface.co/IlyaGusev/saiga_yandexgpt_8b

    Pretrain-версия младшей модели — YandexGPT 5 Lite Pretrain — опубликована в свободном доступе и будет полезна разработчикам, которые дообучают базовые версии моделей под свои задачи. Дообученная нами на её основе instruct-версия в ближайшее время станет доступна через API. 

    Плюсы

    1. Яндекс заопенсорсил топологию своей модели Алисы по политическому решению

    Это самая годная топология на рынке, не только для русского языка, а вообще: значительно лучше Mistral NeMo, Llama 3.1, Nemotron, Deepseek и других

    2. При вызове инструментов ориентируется на required параметры

    Важное отличие от Nemotron mini

    3. Не вызывает инструменты рекурсивно

    Критическое отличие от Nemotron mini: рекурсивный вызов инструмента создаст deadlock чата. Эта модель таким прелестным качеством не обладает

    4. Не запустится на ноутбуке, но системный блок с видеокартой 3060 тянет эту модель

    Если не работает на Saiga/YandexGPT, лучше только откат до OpenAI

    Минусы

    1. Так как опенсорс топологии был политическим, Яндекс утаил датасет.

    Благо, есть Saiga: докинув 10% русского текста в датасет для дообучения LLama тупо повезло и модель сама выучила русский

    2. Лексер LMStudio не может парсить случаи, когда модель запрашивает вызов двух инструментов одновременно

    При просьбе добавить два товара одновременно в чат к пользователю вместо структурированного tool_calls: IToolCall[] улетает [TOOL_REQUEST]n{"name": "add_to_cart_tool", "arguments": {"title": "Аспирин"}}n[END_TOOL_REQUEST как строка content. Лечится через фильтр сообщений от нейронки на предмет отсутствия JSON вообще, ограничением вызовов инструментов не более одного за сообщение через system prompt и мануальный фильтр выхлопа из completer

    Не стабильным решением проблемы является отлов JSON в сообщении от модели с последующей просьбой исправить ошибки в формате. Но, иногда приводит к рекурсии: модель долго рассуждает и всё равно дает невалидный формат вызова инструмента. Поэтому, стабильным способом выхода из положения при детекте JSON в выходе из модели – очистка переписки и отправка пользователю заглушки: Я не расслышал, не могли бы вы повторить

Настройка среды

Для использования Nemotron потребуется скачать ollama с официального сайта, далее в терминале вбить команду ollama pull nemotron-mini:4b

Ollama CLI

Ollama CLI

Для использования YandexGPT потребуется скачать LMStudio, установить модель через поисковик как на скриншоте

LMStudio HuggingFace

LMStudio HuggingFace

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

LMStudio OpenAI Server

LMStudio OpenAI Server

Пример кода

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

import readline from "readline";

import { randomString, Subject } from "functools-kit";

const clientId = randomString();

const incomingSubject = new Subject();
const outgoingSubject = new Subject();

const ws = new WebSocket(`http://127.0.0.1:1337/?clientId=${clientId}`);

ws.onmessage = (e) => {
  incomingSubject.next(JSON.parse(e.data));
};

ws.onopen = () => {
  outgoingSubject.subscribe((data) => {
    ws.send(JSON.stringify({ data }));
  });
};

ws.onclose = () => {
  console.log("Connection closed");
  process.exit(-1);
};

ws.onerror = () => {
  console.log("Connection error");
  process.exit(-1);
};

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
});

const askQuestion = () => {
  rl.question("pharma-bot => ", async (input) => {
    if (input === "exit") {
      rl.close();
      return;
    }

    console.time("Timing");
    await outgoingSubject.waitForListener();
    await outgoingSubject.next(input);
    const { agentName, data } = await incomingSubject.toPromise();
    console.timeEnd("Timing");

    console.log(`[${agentName}]: ${data}`);

    askQuestion();
  });
};

askQuestion();

rl.on("close", () => {
  process.exit(0);
});

Код сервера следующий. Чтобы переподключить агента к другому провайдеру LLM, меняем completion: CompletionName.NemotronMiniCompletion на completion: CompletionName.SaigaYandexGPTCompletion,

import {
  Adapter,
  addAgent,
  addCompletion,
  addSwarm,
  addTool,
  commitFlush,
  commitToolOutput,
  emit,
  execute,
  getAgentName,
  session,
} from "agent-swarm-kit";
import type { ServerWebSocket } from "bun";
import { singleshot, str } from "functools-kit";
import { Ollama } from "ollama";
import OpenAI from "openai";

const getOllama = singleshot(
  () => new Ollama({ host: "http://127.0.0.1:11434" })
);

const getOpenAI = singleshot(
  () => new OpenAI({ baseURL: "http://127.0.0.1:12345/v1", apiKey: "noop" })
);

enum CompletionName {
  NemotronMiniCompletion = "nemotron_mini_completion",
  SaigaYandexGPTCompletion = "saiga_yandex_gpt_completion",
}

enum AgentName {
  TestAgent = "test_agent",
}

enum ToolName {
  AddToCartTool = `add_to_cart_tool`,
}

enum SwarmName {
  TestSwarm = "test_swarm",
}

addCompletion({
  completionName: CompletionName.NemotronMiniCompletion,
  getCompletion: Adapter.fromOllama(getOllama(), "nemotron-mini:4b"),
});

addCompletion({
  completionName: CompletionName.SaigaYandexGPTCompletion,
  getCompletion: Adapter.fromOpenAI(getOpenAI(), "saiga_yandexgpt_8b_gguf"),
});

addAgent({
  agentName: AgentName.TestAgent,
  completion: CompletionName.SaigaYandexGPTCompletion,
  prompt: str.newline(
    "Вы являетесь агентом по продаже фармацевтических товаров.",
    "Предоставьте мне консультацию по фармацевтическому продукту"
  ),
  system: [
    `Чтобы добавить фармацевтический продукт в корзину, вызовите следующий инструмент: ${ToolName.AddToCartTool}`,
  ],
  tools: [ToolName.AddToCartTool],
});

addTool({
  toolName: ToolName.AddToCartTool,
  validate: async ({ params }) => true,
  call: async ({ toolId, clientId, agentName, params }) => {
    console.log(ToolName.AddToCartTool, params);
    await commitToolOutput(
      toolId,
      `Фармацевтический продукт ${params.title} успешно добавлен.`,
      clientId,
      agentName
    );
    await emit(
      `Продукт ${params.title} добавлен в корзину. Вы желаете оформить заказ?`,
      clientId,
      agentName
    );
  },
  type: "function",
  function: {
    name: ToolName.AddToCartTool,
    description:
      "Добавить фармацевтический продукт в корзину. Обязательно передай параметр title.",
    parameters: {
      type: "object",
      properties: {
        title: {
          type: "string",
          description: `Название фармацевтического продукта, который нужно добавить в корзину`,
        },
      },
      required: [],
    },
  },
});

addSwarm({
  swarmName: SwarmName.TestSwarm,
  agentList: [AgentName.TestAgent],
  defaultAgent: AgentName.TestAgent,
});

type WebSocketData = {
  clientId: string;
  session: ReturnType<typeof session>;
};

Bun.serve({
  fetch(req, server) {
    const clientId = new URL(req.url).searchParams.get("clientId")!;
    console.log(`Connected clientId=${clientId}`);
    server.upgrade<WebSocketData>(req, {
      data: {
        clientId,
        session: session(clientId, SwarmName.TestSwarm),
      },
    });
  },
  websocket: {
    async message(ws: ServerWebSocket<WebSocketData>, message: string) {
      const { data } = JSON.parse(message);
      const answer = await ws.data.session.complete(data);
      ws.send(
        JSON.stringify({
          data: answer,
          agentName: await getAgentName(ws.data.clientId),
        })
      );
    },
  },
  hostname: "0.0.0.0",
  port: 1337,
});

Заключение

Исходя из вышеизложенных тезисов, можно сделать следующие выводы

  1. Для каждой новой локализации чата потребуется делать новый рой агентов

    Языковые модели начинают путаться, если system prompt содержит информацию на чужом для пользователя языке: в русскоязычном тексте появляются сегментарные англоязычные включения

  2. По OpenSource моделям есть продвижение, но сейчас закрытые модели лидируют

    Адаптер для переключения с OpenAI на локальную модель критически важен для отлова edge cases: так как бесплатные модели часто глючат, на них проще исправлять ошибки. Прод среду же всё ещё стабильнее запускать на закрытой модели

  3. Если проект нацелен на русскоязычную аудиторию – берите Saiga/YandexGPT

    Мной так же была произведена попытка установить в LMStudio Vikhr-YandexGPT-5-Lite-8B, но инструменты не вызывались. Без инструментов, языковая модель не имеет смысл, так как не работают интеграции в сторонние сервисы

Автор: tripolskypetr

Источник

Рейтинг@Mail.ru
Rambler's Top100