> For the complete documentation index, see [llms.txt](https://docs.ncteam.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.ncteam.io/ai/obuchenie-ii-vektornomu-metodu.md).

# Обучение ИИ векторному методу

Эксперт: Юлия Голощапова

**Искусственный интеллект стал надёжным помощником** в решении множества повседневных и профессиональных задач — от написания текстов до анализа данных. Наибольшую популярность обрели **Генеративные модели ИИ** благодаря своей способности создавать новые данные, опираясь на информацию, использованную в процессе их обучения. Объясняя простым языком, они могут создавать тексты, изображения, музыку или другие типы контента, имитируя стиль и структуру исходных данных, при этом формируя уникальные и оригинальные варианты ответа, не являющиеся дословным повторением исходного материала.

Одна из проблем, с которой часто сталкиваются пользователи, которые используют **Генеративную модель ИИ** – получение ложной или искаженной информации. Искусственный интеллект может "уверенно" отвечать неправильно, если не ограничен контекстом или не знает, где искать достоверный источник. Данное явление называют **"галлюцинацией ИИ"**.

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

Решением становится **метод подбора** — подход, при котором ИИ не "выдумывает" ответ, а **выбирает наиболее релевантный фрагмент из заранее подготовленной базы знаний**.

В данной инструкции мы подробно рассмотрим процесс **обучения ИИ методу подбора**.

### Что такое метод подбора?

{% hint style="info" %}
**Метод подбора** — это способ, с помощью которого искусственный интеллект **находит наиболее подходящий объект** из множества возможных, основываясь на определённой логике или метрике сходства. Такой подход позволяет извлекать наиболее релевантные данные из подготовленного набора, минимизируя риск ошибки.
{% endhint %}

### Для обучения нам понадобятся следующие платформы и сервисы:

* NocoDB
* n8n
* Pinecone
* OpenAI

### Формирование базы данных

В первую очередь нам необходимо подготовить данные для загрузки в **ИИ** и сформировать базу данных в формате **вопрос-ответ**. Сделать это можно на платформе **NocoDB**, однако быстрее и проще будет создать подходящий список в **Google Sheets**.

{% stepper %}
{% step %}
Открываем Google Sheets и создаем таблицу в нем:

![](https://content.gitbook.com/content/adGXspCXfuLDmMvBstfI/blobs/ZzGfT1pgF02RSdBkGOj8/image)

* В созданной таблице создаем две колонки – **question** (вопрос) и **answer** (ответ).
  {% endstep %}

{% step %}
Берём интересующий материал и формируем вопросы и ответы.

<figure><img src="https://1945201336-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FadGXspCXfuLDmMvBstfI%2Fuploads%2FEA3Gl8h7fnaHXGpU7jTv%2Fimage.png?alt=media&amp;token=dfa44ea6-2d50-4ff3-a3f8-41109be57db5" alt=""><figcaption></figcaption></figure>

**!Важно:** Чем больше будет синонимичных вопросов, тем более точно **ИИ** будет подбирать ответ. Лучше сделать минимум вопросов 10 на каждый ответ. **Один вопрос – одна строка.**

Также советуем делать в **Google Sheet** не более **150 строчек** на каждом листе, чтобы в будущем при загрузке в базу **NocoDB** у нас не возникло проблем с импортированием.
{% endstep %}

{% step %}
После формирования базы вопросов и ответов скачиваем каждый лист в формате **CSV**.

![](https://content.gitbook.com/content/adGXspCXfuLDmMvBstfI/blobs/ifqyBmokOtDZbZIfBp4v/image)
{% endstep %}

{% step %}
Открываем **NocoDB** и создаем в нем новую базу, для этого нажимаем на кнопочку **Create Base**.

![](https://content.gitbook.com/content/adGXspCXfuLDmMvBstfI/blobs/MXi885YoMfXqRCBmZqmc/image)
{% endstep %}

{% step %}
В открывшемся окошке даем наименование и еще раз жмем на кнопку **Create Base**.

<figure><img src="https://1945201336-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FadGXspCXfuLDmMvBstfI%2Fuploads%2FF5nOwl1wyjxnDRNG3mF7%2Fimage.png?alt=media&amp;token=a55cf91c-1aae-44bf-b32c-a6f3b8822546" alt=""><figcaption></figcaption></figure>
{% endstep %}

{% step %}
Перед импортированием таблицы из **Google Sheet** мы создаем новую таблицу.

<figure><img src="https://1945201336-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FadGXspCXfuLDmMvBstfI%2Fuploads%2FB9wI6KzW1NwBMEcvikMb%2Fimage.png?alt=media&amp;token=669a7c2c-4560-4fe5-bd4d-197631d54dd1" alt=""><figcaption></figcaption></figure>
{% endstep %}

{% step %}
Присваиваем ей наименование и жмем **Create Table**.

<figure><img src="https://1945201336-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FadGXspCXfuLDmMvBstfI%2Fuploads%2Fhv9KvEuOUMZMloJam6ao%2Fimage.png?alt=media&amp;token=3880127f-2588-4d75-956b-c553207b6ade" alt=""><figcaption></figcaption></figure>

У нас по умолчанию открывается вот такое поле:

<figure><img src="https://1945201336-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FadGXspCXfuLDmMvBstfI%2Fuploads%2FkCzPtvPPrDwkX44i8nzy%2Fimage.png?alt=media&amp;token=7fa75ded-aac1-40cd-b3b2-8ce8b28833f7" alt=""><figcaption></figcaption></figure>
{% endstep %}

{% step %}
Поскольку таблица у нас пустая, мы должны ее заполнить колонками и выбрать в них необходимый тип данных для записи. Для начала переименуем по умолчанию созданную колонку с названием **Title**. Сделать это можно, нажав на стрелочку вниз.

<figure><img src="https://1945201336-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FadGXspCXfuLDmMvBstfI%2Fuploads%2FmwTDZersJ1xpSed8z00w%2Fimage.png?alt=media&amp;token=47d51a1a-5066-48ac-9458-b574df793835" alt=""><figcaption></figcaption></figure>
{% endstep %}

{% step %}
Данная кнопочка развернет параметры колонки. В раскрывшемся списке действий выбираем **Edit field**.

<figure><img src="https://1945201336-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FadGXspCXfuLDmMvBstfI%2Fuploads%2FOy325oqqkHS5SAhbKNX2%2Fimage.png?alt=media&amp;token=bb802fe7-9fa9-472c-b912-87a84b0f4d8c" alt=""><figcaption></figcaption></figure>
{% endstep %}

{% step %}
После этого появится окошко редактирования названия столбца и типа данных.

<figure><img src="https://1945201336-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FadGXspCXfuLDmMvBstfI%2Fuploads%2FTwe3rZwurZ4RAKLfKaSs%2Fimage.png?alt=media&amp;token=ba97df4e-9e71-405d-ad42-e7c1039be250" alt=""><figcaption></figcaption></figure>

В нашем случае лучше выбрать **Long text**, чтобы было удобнее просматривать таблицу.

<figure><img src="https://1945201336-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FadGXspCXfuLDmMvBstfI%2Fuploads%2FK9SHMRwjAOCZ9it7FP6p%2Fimage.png?alt=media&amp;token=ccf50935-2e5f-447e-8848-7318a6ecebc8" alt=""><figcaption></figcaption></figure>
{% endstep %}

{% step %}
Сохраняем название и тип данных по кнопке **Update Field.**

<figure><img src="https://1945201336-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FadGXspCXfuLDmMvBstfI%2Fuploads%2FWxYEK67GlAqA1uUEx0Cr%2Fimage.png?alt=media&amp;token=9d9f8121-4316-44db-af4c-bc7fd869ced8" alt=""><figcaption></figcaption></figure>
{% endstep %}

{% step %}
Теперь нам нужно создать еще 4 колонки. Сделать это можно по кнопке "+"

<figure><img src="https://1945201336-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FadGXspCXfuLDmMvBstfI%2Fuploads%2FzzgWtncc5hKY5eH1DGnO%2Fimage.png?alt=media&amp;token=80cb5f7b-14e4-4550-a052-558bdecfdbec" alt=""><figcaption></figcaption></figure>

Всего у нас должно получиться 5 колонок со следующим типом данных:

a. **question**\
&#x20;    Field type – Long text

b. **answer**\
&#x20;    Field type – Long text

c. **emdedded**\
&#x20;    Field type – Checkbox

d. **to\_embed**\
&#x20;    Field type – Checkbox

А еще в значении **Defalut value** должна стоять галочка

<figure><img src="https://1945201336-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FadGXspCXfuLDmMvBstfI%2Fuploads%2FNZCe8OrX8y5wn3fBjpJI%2Fimage.png?alt=media&amp;token=9c2f9f0e-f6e3-4627-8abd-c4909cfc36dd" alt=""><figcaption></figcaption></figure>

e. **to\_delete**

Field type – Checkbox

В конечном итоге у нас должно это выглядеть так:

<figure><img src="https://1945201336-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FadGXspCXfuLDmMvBstfI%2Fuploads%2FbB0ZlOEuaf9fEnnvaUHX%2Fimage.png?alt=media&amp;token=0fcfcb18-b049-47b1-82df-f949b4a9d2d6" alt=""><figcaption></figcaption></figure>
{% endstep %}

{% step %}
Импортируем данные. Для того чтобы загрузить нашу имеющуюся таблицу с вопросами и ответами, нам необходимо нажать на три вертикальных строчки в верхней панели, затем **Upload → Upload CSV**

<figure><img src="https://1945201336-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FadGXspCXfuLDmMvBstfI%2Fuploads%2FY0WgrYHqtkrHbr6npNVw%2Fimage.png?alt=media&amp;token=b56c33f2-3435-404e-833e-6f233cc689c4" alt=""><figcaption></figcaption></figure>
{% endstep %}

{% step %}
Перед нами откроется окошко загрузки файлов. Перетягиваем таблицу из загрузок, либо загружаем по кнопке из внутреннего хранилища компьютера.

<figure><img src="https://1945201336-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FadGXspCXfuLDmMvBstfI%2Fuploads%2FXKz3I2z5eKZWrFHmeBHV%2Fimage.png?alt=media&amp;token=b30754d4-0b82-4ab6-9b21-eb8b8a56d210" alt=""><figcaption></figcaption></figure>
{% endstep %}

{% step %}
Нажимаем **Import**.

<figure><img src="https://1945201336-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FadGXspCXfuLDmMvBstfI%2Fuploads%2FubXZsjWMyxPsj1tct6C7%2Fimage.png?alt=media&amp;token=d6f37b3d-bed6-41c9-978c-bed23e9b816c" alt=""><figcaption></figcaption></figure>
{% endstep %}

{% step %}
**Важно: Названия колонок в обеих таблицах должны совпадать!** Либо необходимо вручную выбрать, какой столбец из **Google Sheets** соответствует столбцу в **NocoDB**. Нажимаем **Import** еще раз, если все верно.

<figure><img src="https://1945201336-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FadGXspCXfuLDmMvBstfI%2Fuploads%2FX3s42UekodcvPYQxyB0O%2Fimage.png?alt=media&amp;token=917cde93-bba2-4ac8-ba23-edbae1dcb13f" alt=""><figcaption></figcaption></figure>
{% endstep %}

{% step %}
При успешном импортировании должен получиться такой результат:

<figure><img src="https://1945201336-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FadGXspCXfuLDmMvBstfI%2Fuploads%2FDCFdebmjjf6lz1Q2ltLo%2Fimage.png?alt=media&amp;token=547c13a9-487a-4cb0-a902-e2ea7dfb38ee" alt=""><figcaption></figcaption></figure>
{% endstep %}
{% endstepper %}

***

### Создание индексов в Pinecone

**Pinecone** — это облачная векторная база данных, которую мы будем использовать для работы с искусственным интеллектом.

Когда мы передаём в ИИ текст (например, вопрос или описание), он преобразует его в **вектор** – массив чисел, который отражает смысл и контекст данного текста. Эти векторы можно сравнивать между собой: чем они ближе друг к другу в многомерном пространстве, тем более **они схожи** с текстами, из которых были получены.

При работе с большим объёмом векторных данных важно **эффективно находить похожие объекты**. Для этого используется **индекс** – специальная структура данных, оптимизированная для быстрого поиска схожих векторов.

{% stepper %}
{% step %}
Откроем интерфейс **Pinecone** и нажмем кнопку **Create index**.

![](https://content.gitbook.com/content/adGXspCXfuLDmMvBstfI/blobs/Oix0WLTeECCYFf5RcWjW/image)
{% endstep %}

{% step %}
После нажатия кнопки откроется окошко с настройками индекса. Здесь мы пишем название нашего индекса и ставим галочку на Custom settings.

![](https://content.gitbook.com/content/adGXspCXfuLDmMvBstfI/blobs/iaIF4cBFwpQQz4IJsZ49/image)
{% endstep %}

{% step %}
В разделе **Configuration** указываем размерность:

В поле **Dimension** вводим значение – 3072.

![](https://content.gitbook.com/content/adGXspCXfuLDmMvBstfI/blobs/I5TAMoj8rJSgqMSulpSm/image)
{% endstep %}

{% step %}
Затем нажимаем **Create index**.

![](https://content.gitbook.com/content/adGXspCXfuLDmMvBstfI/blobs/y9fMLJCHm2UPIJZAB0Pe/image)
{% endstep %}

{% step %}
После создания индекс появится в списке. Скопируйте его ссылку – она потребуется в дальнейшем.

![](https://content.gitbook.com/content/adGXspCXfuLDmMvBstfI/blobs/Tk4WazYhNYsHPlis1r4t/image)
{% endstep %}
{% endstepper %}

## Обучение ИИ по базе знаний&#x20;

1. Открываем **n8n** и создаем в нем новый **Workflow**
2. Наша цепочка будет выглядеть следующим образом:

   <figure><img src="https://1945201336-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FadGXspCXfuLDmMvBstfI%2Fuploads%2FaI0vzsW8YSqaTlTcPbHB%2Fimage.png?alt=media&amp;token=bc4676a6-f207-419c-b2df-cd7179b99830" alt=""><figcaption></figcaption></figure>

### Краткое описание узлов цепочки:

**Schedule Trigger** — запускает процесс по расписанию.

**NocoDB** — получает данные из таблицы NocoDB (вопросы и ответы).

**HTTP Request** — отправляет запрос к OpenAI для генерации эмбеддингов.

**Embeddings** — формирует массив векторов.

**50 Vectors** — подготавливает массив из 50 векторов для загрузки.

**Upsert** — загружает векторы в Pinecone.

**Mark as Embedded** — помечает обработанные строки в базе как embedded.<br>

### Рассмотрим параметры каждого узла более детально: <a href="#rassmotrim-parametry-kazhdogo-uzla-bolee-detalno" id="rassmotrim-parametry-kazhdogo-uzla-bolee-detalno"></a>

#### **Schedule Trigger**

В данном узле мы устанавливаем временной интервал, с которым будет запускаться цепочка, если захотим автоматизировать пополнение базы векторов.

![](https://cdn2.buildin.ai/s3/693bad1b-b398-4381-9a35-22590daf3706/image.png?time=1768910400\&token=41866b8b402ec6d7c8e2b9a4edef641a\&role=free)

#### **NocoDB1**

<figure><img src="https://1945201336-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FadGXspCXfuLDmMvBstfI%2Fuploads%2Fb9IEI2LIspwpkUb3ujUY%2Fimage.png?alt=media&amp;token=27bb8a02-173a-4ecf-bf24-9167badfb544" alt=""><figcaption></figcaption></figure>

{% hint style="warning" %}
**!Важный момент.** В **n8n** у вас должны быть созданы **Credential** с **NocoDB** и **Pinecone**. При создании **Credential** для **NocoDB** требуется указать **Название** и **API Token** А при создании **Credential** для **Pinecone** требуется **Название**, **Ключ API**

**Это нужно для получения доступа к сервисам.**<br>
{% endhint %}

В текущем узле мы выбираем нужный **Credential**, **Project Name** и **Table name** (пространство в NocoDB, база в NocoDB и таблица)

В разделе **Options** в поле **Fields** пишем - I**d,question,answer**. В поле **Filter by Formula** устанавливаем фильтр:

```json
(embedded,eq,false)~and(to_embed,eq,true)~and(question,neq,)~and(question,isnot,null)~and(answer,neq,)~and(answer,isnot,null)~and(to_delete,eq,false)
```

#### HTTP-request

В данном узле мы заполняем параметры для отправки запроса, выбираем метод, пишем адрес. В **Header Parameters** пишем название заголовка **Authorization** и значение **API-ключа**, используемого для доступа к **OpenAI** в формате **Bearar OPENAI\_KEY**.

<figure><img src="https://1945201336-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FadGXspCXfuLDmMvBstfI%2Fuploads%2FKvc7atkLdEPnxQp3Bg9c%2Fimage.png?alt=media&amp;token=7e908c80-eb1d-4928-848b-3b26217efeeb" alt=""><figcaption></figcaption></figure>

В теле запроса в **Body Parameters** мы пишем:

**Name:** `input`\
\
**Value:** `{{ $json.question }}`

Так мы передадим значение вопроса. Также необходимо передать данные о модели ИИ, которая нам нужна:

**Name:** `model`

**Value:** `text-embedding-3-large`

<figure><img src="https://1945201336-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FadGXspCXfuLDmMvBstfI%2Fuploads%2FEWTNTiq84jQuWxoZ0kt4%2Fimage.png?alt=media&amp;token=420128be-4e99-4b4c-b884-93a53b204cde" alt=""><figcaption></figcaption></figure>

#### **Embeddings**

<figure><img src="https://1945201336-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FadGXspCXfuLDmMvBstfI%2Fuploads%2FNdeVX80FgvRx6CHKQmAk%2Fimage.png?alt=media&amp;token=e70616d9-a60a-46f8-afe9-4512b303734d" alt=""><figcaption></figcaption></figure>

#### **50 vectors**

В ноде **code** мы пишем код:

```json
const vectors = $input.all()

.map(i => i.json)

.map((vector,index) => {

return {

values: vector.data[0].embedding,

id: "Id-" + vector.Id.toString(),

metadata: {

question: vector.question,

answer: vector.answer

}

}

})

const mark_as_embedded = vectors.map(vector => ({Id: Number(vector.id.split('-')[1]), embedded: true}))

return [{vectors,mark_as_embedded}];
```

Данный код обрабатывает данные, полученные после создания эмбеддингов, и готовит их для загрузки в векторную базу **Pinecone**, а также для пометки в базе **NocoDB**, что эти строки уже были обработаны.

#### Upsert

Ранее мы создавали индекс в **Pinecone** и сохраняли ссылку. Ее мы вставляем в поле **URL** и дописываем в адресе **/vectors/upsert**, чтобы у нас получилось:

<mark style="color:red;">https\://\<cсылка\_на\_pinecone></mark>**/vectors/upsert**

Установим следующие параметры:

* **Method:** `POST`
* **URL:** <mark style="color:red;">https\://\<cсылка\_на\_pinecone></mark>**/vectors/upsert**
* **Authentication:** `Predefined`
* **Credential Type:** `PineconeApi`
* **PineconeApi:** Выбираем заранее сохранённый API-ключ **Pinecone** для авторизации.

<figure><img src="https://1945201336-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FadGXspCXfuLDmMvBstfI%2Fuploads%2FzkEdqNJZufoQ60P6pcX2%2Fimage.png?alt=media&amp;token=3d2665c8-d495-4ea2-a452-5e322428223f" alt=""><figcaption></figcaption></figure>

В **Header Parameters:**

**Name:** `accept`

**Value:** `application/json`<br>

<figure><img src="https://1945201336-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FadGXspCXfuLDmMvBstfI%2Fuploads%2FMbfIO5KA6YNu8Btx5Gkg%2Fimage.png?alt=media&amp;token=12f0ef15-9710-4dc7-8dbc-dfa3799e051d" alt=""><figcaption></figcaption></figure>

В **Body Parameters**:

**Name:** `vectors`

**Value:** `{{ $json.vectors }}`

<figure><img src="https://1945201336-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FadGXspCXfuLDmMvBstfI%2Fuploads%2FS3wcqvTqggk2kbNH83Px%2Fimage.png?alt=media&amp;token=d3bad308-b38b-45e6-bd08-015e7f9bb693" alt=""><figcaption></figcaption></figure>

#### Mark as Embedded

#### &#xD;В заключительном узле цепочки обновляем данные таблицы **NocoDB**. Для этого в **URL** указываем адрес базы **NocoDB** со следующей структурой:

https\://<mark style="color:red;"><Адрес\_nocodb></mark>/api/v2/tables/<mark style="color:red;"><айди\_таблицы></mark>/records.

**Выбираем следующие значения:**

* **Method:** `PATCH`
* **URL:** https\://<mark style="color:red;"><Адрес\_nocodb></mark>/api/v2/tables/<mark style="color:red;"><айди\_таблицы></mark>/records.
* **Authentication:** `Predefined Credential type`
* **Credential Type**: `NocoDB API Token`

<figure><img src="https://1945201336-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FadGXspCXfuLDmMvBstfI%2Fuploads%2FOBpHFG5iddb4FHLGwERv%2Fimage.png?alt=media&amp;token=c8763418-dc26-4656-b97f-47828cd32d3b" alt=""><figcaption></figcaption></figure>

* **NocoDB API Token:** (выбираем **Credential** нужной базы **NocoDB)**

В **Header Parameters** указываем:

**Name:** `accept`

**Value:** `application/json`

В **Body** пишем в поле **JSON**, меняя тип с **Fixed** на **Expression**:

```json
{{ JSON.stringify($('50 Vectors').first().json.mark_as_embedded) }}
```

<figure><img src="https://1945201336-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FadGXspCXfuLDmMvBstfI%2Fuploads%2Fzn0B0fkVwn5ScqkfojBG%2Fimage.png?alt=media&amp;token=3c338df7-0c5e-4835-a825-c62d9f79da8b" alt=""><figcaption></figcaption></figure>

3. Сохраняем **Workflow** в **n8n**
4. Нажимаем на кнопочку запуска

   <figure><img src="https://1945201336-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FadGXspCXfuLDmMvBstfI%2Fuploads%2FKLp88UjNGWCmOFGQ4Oia%2Fimage.png?alt=media&amp;token=2b4ac099-4225-45a2-aa80-88d07d06f7bf" alt=""><figcaption></figcaption></figure>
5. После запуска цепочки в таблице появятся галочки в колонке **embedded**. Это значит, что данные вопросы и ответы были загружены в векторную базу **Pinecone**

   <figure><img src="https://1945201336-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FadGXspCXfuLDmMvBstfI%2Fuploads%2F1ypdOEdqPq2JfV2014Bc%2Fimage.png?alt=media&amp;token=a9231e24-130c-4b33-8d34-6474b858361d" alt=""><figcaption></figcaption></figure>

## Настройка сценария в Smartbot

1. Заходим в личный кабинет **Smartbot** и переходим в раздел **"Сценарии"**.

   <figure><img src="https://1945201336-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FadGXspCXfuLDmMvBstfI%2Fuploads%2F96P5ZH2O2tjPHkwSB5iH%2Fimage.png?alt=media&amp;token=f54594a6-9666-4e7e-8b98-0c6dfbba801d" alt=""><figcaption></figcaption></figure>
2. Нажимаем на кнопку **"Создать сценарий"**

   <figure><img src="https://1945201336-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FadGXspCXfuLDmMvBstfI%2Fuploads%2FKVkHfCEufWxfv4wadGUO%2Fimage.png?alt=media&amp;token=b88c420a-2fdf-42ac-b742-ec041d8e267f" alt=""><figcaption></figcaption></figure>
3. В открывшемся окошке пишем название сценария, затем нажимаем **"Создать"**

   <figure><img src="https://1945201336-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FadGXspCXfuLDmMvBstfI%2Fuploads%2FSArYxSuJQJ4vb5L0hzNL%2Fimage.png?alt=media&amp;token=40e30294-3d50-4799-a7e6-32daaedeb8e5" alt=""><figcaption></figcaption></figure>
4. **Рассмотрим схематически, как должен выглядеть сценарий, и разберем каждый блок по отдельности:**

   <figure><img src="https://1945201336-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FadGXspCXfuLDmMvBstfI%2Fuploads%2FpuVwahLonsNEcJkQKpOE%2Fimage.png?alt=media&amp;token=1bd5ef09-cdfa-48a3-8118-a4b12addc864" alt=""><figcaption></figcaption></figure>

**Наш сценарий будет состоять из 7 блоков:**

1. Нет подходящего сценария
2. Выполнить SmartQuery
3. Выполнить SmartQuery
4. Отправить HTTP-запрос
5. Webhook
6. Выполнить SmartQuery
7. Отправить сообщение

#### **Блок 1: Нет подходящего сценария**

Реагирует на любое сообщение пользователя в боте. Он запускает всю цепочку сценария.

<figure><img src="https://1945201336-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FadGXspCXfuLDmMvBstfI%2Fuploads%2FPRc1m4Paz9uDzO8RBUAv%2Fimage.png?alt=media&amp;token=9f5636f4-7a8f-44d5-8752-496f540f2018" alt=""><figcaption></figcaption></figure>

#### **Блок 2: Выполнить SmartQuery**

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

<figure><img src="https://1945201336-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FadGXspCXfuLDmMvBstfI%2Fuploads%2FRez9MALblDgUgmn9eBZD%2Fimage.png?alt=media&amp;token=d1e19151-0b2b-4dee-9cbc-257b49da785d" alt=""><figcaption></figcaption></figure>

#### **Блок 3: Выполнить SmartQuery**

В данном блоке мы подготавливаем данные, создаем URL и тело запроса.

<figure><img src="https://1945201336-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FadGXspCXfuLDmMvBstfI%2Fuploads%2FBzvgIXWlF6wAWta0ofGo%2Fimage.png?alt=media&amp;token=a7ba4ede-606f-4029-afd2-a73635bf956b" alt=""><figcaption></figcaption></figure>

```
%string_temp% = %n8n_url% + "/webhook/test_new_request"

%body% = {
    "question": %message_text%,
    "user_id": %user_id%
}

%response_data% = {}
%response_data_status% = 0
```

**Используемые переменные:**

`%string_temp%` — (тип: строка) итоговый **URL**.

`%body%` — (тип: словарь) передаём вопрос и **ID** пользователя.

`%n8n_url%` — (тип: строка) переменная со ссылкой на ваш сервер **n8n**.

**!Важно:** **URL** должен совпадать с **URL** вызова вебхука в **n8n.**

#### **Блок 4: Отправить HTTP-запрос**

![](https://content.gitbook.com/content/adGXspCXfuLDmMvBstfI/blobs/qT5vp0VtZ3Tz7fLjyPs0/image)

Устанавливаем следующие параметры:

* **Метод:** `POST`
* **URL:** `%string_temp%`
* **Тип тела:** `Текст`
* **Значение тела:** `{{ %body% | to_json }}`

<figure><img src="https://1945201336-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FadGXspCXfuLDmMvBstfI%2Fuploads%2F5A22kLByg4VaMMkwuaj4%2Fimage.png?alt=media&amp;token=f252a10b-0861-4bca-baf3-e39ce8c5db97" alt=""><figcaption></figcaption></figure>

**В заголовках:**

* **Наименование:** content-type
* **Значение:** `application/json`

#### **Блок 5: Webhook**

Через этот блок мы получаем ответ из **n8n.** Чтобы он работал, мы должны создать **API-токен,** либо выбрать уже существующий.

<figure><img src="https://1945201336-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FadGXspCXfuLDmMvBstfI%2Fuploads%2FxtqciubOlS84rtXpJFrO%2Fimage.png?alt=media&amp;token=da4c812d-fc6a-49e9-ba1f-bc9b6bda4dd3" alt=""><figcaption></figcaption></figure>

В **API-токены** выбираем **"Создать токен".**

<figure><img src="https://1945201336-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FadGXspCXfuLDmMvBstfI%2Fuploads%2Fz8mt5wzIFoTu9RCgmUQy%2Fimage.png?alt=media&amp;token=f8c18cf0-7131-426e-93c8-fd66fc31959b" alt=""><figcaption></figcaption></figure>

В открывшемся окошке нажимаем на кнопку **"Cоздать токен".**

<figure><img src="https://1945201336-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FadGXspCXfuLDmMvBstfI%2Fuploads%2FUB2kLBmQv1FB3jopihDZ%2Fimage.png?alt=media&amp;token=47a5137f-c2e9-4012-8758-1fd0a1963e7e" alt=""><figcaption></figcaption></figure>

Придумываем название и создаем токен.

<figure><img src="https://1945201336-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FadGXspCXfuLDmMvBstfI%2Fuploads%2FqwdewS3ml7Hu3E6eXEKs%2Fimage.png?alt=media&amp;token=a3d34f3a-be0a-414d-812e-22f91054fbe5" alt=""><figcaption></figcaption></figure>

Выбираем созданный токен и канал.

<figure><img src="https://1945201336-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FadGXspCXfuLDmMvBstfI%2Fuploads%2F5lX1a0OnlnOD7JuN8krS%2Fimage.png?alt=media&amp;token=d9f721c4-c87f-423b-89c8-fb31ff17e046" alt=""><figcaption></figcaption></figure>

Данные из **Webhook** нам понадобятся в дальнейшей настройке **Workflow** в **n8n.**

#### **Блок 6: Выполнить SmartQuery**

Извлекаем текст ответа из **Webhook** и сохраняем его в переменную `%bot_message%`.

```json
%bot_message% = %public_api_data%['answer']
```

<figure><img src="https://1945201336-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FadGXspCXfuLDmMvBstfI%2Fuploads%2FmpPYtJYjVAurx8bcdXlr%2Fimage.png?alt=media&amp;token=68efb26b-12e5-452a-8576-b52e59e7b275" alt=""><figcaption></figcaption></figure>

#### **Блок 7: Отправить сообщение**

Выводим значение переменной `%bot_message%`в блоке **"Отправить сообщение"**.

<figure><img src="https://1945201336-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FadGXspCXfuLDmMvBstfI%2Fuploads%2FZVpDyX9ZhvZxMEah0Wwr%2Fimage.png?alt=media&amp;token=bb2fb192-02ab-43a2-973c-87e49969b51f" alt=""><figcaption></figcaption></figure>

## **Отправка ответа из Pinecone в Smartbot** <a href="#otpravka-otveta-iz-pinecone-v-smartbot" id="otpravka-otveta-iz-pinecone-v-smartbot"></a>

В данной части инструкции мы по шагам разберём, **как настроить рабочий процесс в n8n**, который будет:

* принимать запрос от пользователя через **Smartbot**
* искать наиболее подходящий ответ через **Pinecone** (векторную БД)
* отправлять его обратно пользователю

**Создаём Workflow в n8n**

1. Открываем **n8n**. Создаем новый **workflow**.
2. Наша логика будет выглядеть следующим образом:

   <figure><img src="https://1945201336-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FadGXspCXfuLDmMvBstfI%2Fuploads%2FRcOy09rFkAXPzKVNxzen%2Fimage.png?alt=media&amp;token=66446cb7-1491-4a43-89c3-aca138b94a5e" alt=""><figcaption></figcaption></figure>

**Краткое описание узлов цепочки:**

**Webhook** — принимает запрос от Smartbot (вопрос пользователя).

**Get vectorized** — отправляет вопрос в OpenAi для получения вектора.

**Get the nearest reply** — ищет наиболее близкие к вопросу вектора (совпадения) в Pinecone.

**if** — проверяет, нашлось ли совпадение.

**Code (успех)** — формирует тело ответа из Pinecone.

**HTTP Request (успех)** — отправляет ответ пользователю в Smartbot.

**Code (неудача)** — формирует тело ответа в случае отсутствия совпадения.

**HTTP Request (неудача)** — отправляет ответ в Smartbot.<br>

### Рассмотрим параметры каждого узла более детально:

#### Webhook

Данный узел запускает весь **workflow**. Через него мы принимаем данные из **Смартбота**, а именно, вопрос пользователя и его **ID**.

<figure><img src="https://1945201336-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FadGXspCXfuLDmMvBstfI%2Fuploads%2FFx9elN2zoAGgwHLVD52j%2Fimage.png?alt=media&amp;token=bcd27308-27f7-4214-87f2-e1811b82598a" alt=""><figcaption></figcaption></figure>

**Параметры узла:**

* **Method:** `POST`
* **Path:** (часть **URL**, по которой по которой вызывается этот **Webhook**)
* **Respond:** `Immediately`

**!Важный момент:** **Path** должен быть идентичен тому, который мы указывали в **Смартботе** ранее.

<figure><img src="https://1945201336-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FadGXspCXfuLDmMvBstfI%2Fuploads%2Fhqrq8HTERUNfdw3huOHl%2Fimage.png?alt=media&amp;token=c3a4b703-fb36-4355-acf3-c833f9f0eb9d" alt=""><figcaption></figcaption></figure>

<figure><img src="https://1945201336-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FadGXspCXfuLDmMvBstfI%2Fuploads%2FT0lmUodN4C8VjbzQgbHv%2Fimage.png?alt=media&amp;token=921afbf3-1925-49f2-9ac5-6af13d533d16" alt=""><figcaption></figcaption></figure>

#### **Get vectorized**

Отправляет вопрос в OpenAI и получает его векторное представление.

**Параметры узла:**

* **Method**: `POST`
* **URL**: `https://api.openai.com/v1/embeddings`
* **Authentication**: `Predefined Credential Type`
* **Credential Type**: `OpenAi`
* **OpenAi:** (Выбираем нужный Credential OpenAi)
* **Model**: `text-embedding-3-large`

<figure><img src="https://1945201336-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FadGXspCXfuLDmMvBstfI%2Fuploads%2FAO2kVRdRu5sXGsouFhCD%2Fimage.png?alt=media&amp;token=bae012b3-b3d6-4628-9109-877530861ad0" alt=""><figcaption></figcaption></figure>

В **Body Parameters:**

**Name:** `input`

**Value:** `{{ $json.question }}`

Передаем вопрос и данные модели ИИ.

**Name:** `model`

**Value:** `text-embedding-3-large`

<figure><img src="https://1945201336-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FadGXspCXfuLDmMvBstfI%2Fuploads%2FI4UwC6mKLx7tVtZpOJyc%2Fimage.png?alt=media&amp;token=d0e3fb39-1881-4bc1-8bc0-f4547b1c01a6" alt=""><figcaption></figcaption></figure>

#### **Get the nearest reply**

Формируем запрос в векторную базу **Pinecone**, для поиска совпадений вектора вопроса с векторами из базы данных. Для этого заполняем следующие параметры:

* **Method:** `POST`
* **URL:** [https://наpinecone>/query](https://docs.ncteam.io/ai/https:/наpinecone>/query)
* **Authentication:** `Predefined`
* **Credential Type:** `PineconeApi`
* **PineconeApi:** Выбираем заранее сохранённый API-ключ **Pinecone** для авторизации.

<figure><img src="https://1945201336-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FadGXspCXfuLDmMvBstfI%2Fuploads%2FIV0orKrVg7Byk1VrZUVI%2Fimage.png?alt=media&amp;token=145a8ced-5731-47d1-8051-db782abffc8d" alt=""><figcaption></figcaption></figure>

#### **Header Parameters:**

**Name:** `accept`

**Value:** `application/json`

**Body Parameters:**

**Name:** `vector`

**Value:** `{{ $json.data[0].embedding }}`

Векторное представление вопроса пользователя. Отправляем этот вектор, чтобы Pinecone сравнил его с уже сохранёнными векторами и нашёл наиболее подходящие.

**Name:** `topK`

**Value:** `10`

Указываем, сколько **самых близких векторов** (записей) мы хотим получить в ответ. В нашем случае - 10.

**Name:** `includeMetadata`

**Value:** `{{ true }}`

Указываем, что хотим получить из вектора **Pinecone** метаданные о вопросе и ответе.

#### **If**

**Проверяем, были ли найдены совпадения:**

```json
{{ $('Get the nearest reply').first().json.matches }}
```

**=** is not empty

#### **Code**

Создаем **тело (body)** для отправки данных в **Smartbot**.

```json
var data = {
  "answer": $('Get the nearest reply').first().json.matches[0].metadata.answer,//.replaceAll('"', '\"').replaceAll('\n', '\\n'),
  "score": $('Get the nearest reply').item.json.matches[0].score
}

/*Создаем переменную data, чтобы передать: ответ, найденный через Pinecone (answer) и оценку совпадения (score)
*/

var body = {
  "access_token": "d_RzF82z4TXML5_ZnMcrdJS2Y_K8kQNZNzkJZ-ORgI24v1STJEt55EgFXGEaILR6",
  "v": "0.0.1",
  "channel_id": "7779600502",
  "block_id": "6808dbe10aa22020da97a62f",
  "peer_id": $('Webhook').first().json.body.user_id,
  "data": data
}

return {
  body
}
```

В тело запроса добавляем тело вебхука из **Смартбота**:

<figure><img src="https://1945201336-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FadGXspCXfuLDmMvBstfI%2Fuploads%2FX2WmYmHJcSxOtgGJIHvJ%2Fimage.png?alt=media&amp;token=6bc21723-88e6-4b11-abb6-a30a544d2656" alt=""><figcaption></figcaption></figure>

#### **HTTP Request:**

Устанавливаем параметры для отправки подобранного ответа в **Smartbot**:

* **Method:** `POST`
* **URL:** `https://api.smartbotpro.ru/blocks/execute`
* **Authentication:** `None`
* **Body Content Type**: `JSON`
* **Body Parameters:**`{{ JSON.stringify($json.body) }}`

<figure><img src="https://1945201336-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FadGXspCXfuLDmMvBstfI%2Fuploads%2FMvVzkNuBxb7JUJRpSmYY%2Fimage.png?alt=media&amp;token=d0ce96d9-aa98-472b-8401-2bf7a18b5ccf" alt=""><figcaption></figcaption></figure>

#### **Code1 (совпадений не найдено)**

Отправляем ответ в случае отсутcтвия совпадений по векторам.

```json
var data = {
  "answer": 'Ответ не найден',
  "score": 0.00
}

var body = {
   "access_token": "d_RzF82z4TXML5_ZnMcrdJS2Y_K8kQNZNzkJZ-ORgI24v1STJEt55EgFXGEaILR6",
    "v": "0.0.1",
    "channel_id": "7779600502",
    "block_id": "6808dbe10aa22020da97a62f",
    "peer_id": $('Webhook').first().json.body.user_id,
    "data": data
}

return {
  body
}
```

<figure><img src="https://1945201336-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FadGXspCXfuLDmMvBstfI%2Fuploads%2FBkkZsHSnR5WgJB5vw1eK%2Fimage.png?alt=media&amp;token=cd501022-ee4a-4ee0-975d-d60ff95a29dd" alt=""><figcaption></figcaption></figure>

#### **HTTP Request1 (совпадений не найдено)**

Устанавливаем параметры для отправки ответа в **Smartbot**:

* **Method:** `POST`
* **URL:** `https://api.smartbotpro.ru/blocks/execute`
* **Authentication:** `None`
* **Body Content Type**: `JSON`
* **Body Parameters:**`{{ JSON.stringify($json.body) }}`

<figure><img src="https://1945201336-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FadGXspCXfuLDmMvBstfI%2Fuploads%2FdENEE2elf2JkjiLYCqMv%2Fimage.png?alt=media&amp;token=f5c3d181-d442-4457-addd-7192a5dd263a" alt=""><figcaption></figcaption></figure>
