Как юристу выбрать правильный вектор для ответа на вопрос с помощью RAG

В этой заметке продолжаю тему, поднятую здесь. Рассказываю, как применять эмбеддинги, в т.ч. в системе RAG, которая позволит получить релевантную информацию из большого документа (например регламента) или базы данных и отдать пользователю, например менеджеру вашей компании в боте, который я надеюсь вы уже сделали по этому гайду ;)

Для примера я взял Единую оферту Сбермегамаркета отсюда. Закинул её в гугл-табличку и с помощью вот этого кода:

function sberOferta(){ let ss = SpreadsheetApp.openById('ID-таблицы').getSheetByName('Имя листа') let txt_arr = ss.getRange(2,1,ss.getLastRow()-1,1).getValues() for(i=0;i<txt_arr.length;i++){ if (ss.getRange(i+2,2).getValue() === ''){ console.log(i+2) let emb = getEmbedding(txt_arr[i][0]) ss.getRange(i+2,2).setValue(String(emb)) Utilities.sleep(500) } } } function getEmbedding(input) { const apiUrl = 'https://api.openai.com/v1/embeddings'; const options = { method: 'post', headers: { Authorization: `Bearer ЗДЕСЬ ВАШ КЛЮЧ ОТ АПИ ОПЕНАИ`, 'Content-Type': 'application/json', }, muteHttpExceptions: true, payload: JSON.stringify( { "model": "text-embedding-ada-002", "input": input, }), }; const response = UrlFetchApp.fetch(apiUrl, options); const content = response.getContentText(); console.log(content) let json = JSON.parse(content) if (json.error) { return json.error.message } return json.data[0].embedding }

получил в правом столбце эмбеддинги каждого абзаца. Результат можно посмотреть здесь.

Теперь все что нужно сделать, чтобы ответить на вопрос по оферте, это найти наиболее близкий к вопросу эмбеддинг и отдать его чатуГПТ. Сделать это можно вот так:

Первая функция получит вспомогательный текст, который мы отправим чатуГПТ для подготовки ответа. Здесь я взял все эмбеддинги косинусное сходство с которыми давало больше 0,8.

function getHelpTxt(que){ let queEmbed = getEmbedding(que) let maxIndices = []; let txt = `` const ss = SpreadsheetApp.openById('14QtLQDVULl6mEZNt-TI6O9a5QL7WaecYOAxvkDAsFDY').getSheetByName('Единая оферта СММ') let sberEmbedList = ss.getRange(2,2,ss.getLastRow()-1,1).getValues().map((e) => e[0].split(',') ) let cosineSimilarityArr = [] for(i=0;i<sberEmbedList.length;i++){ cosineSimilarityArr.push(cosineSimilarity(queEmbed,sberEmbedList[i])) } console.log(cosineSimilarityArr) for (let i = 0; i < 10; i++) { let maxIndex = cosineSimilarityArr.indexOf(Math.max(...cosineSimilarityArr.filter(num => num > 0.8))); maxIndices.push(maxIndex); cosineSimilarityArr[maxIndex] = -Infinity; } maxIndices.map((i) => { txt += ` ${ss.getRange(i+2, 1).getValue()}` }) console.log(txt) return txt }

Вторая функция непосредственно обращается к чатуГПТ с вопросом, добавляя к нему вспомогательный текст-подсказку, который мы получили выше.

function sberOfertaGPT(que = `Как я узнаю об изменениях в оферте?`) { const helpTxt = getHelpTxt(que) console.log(helpTxt) const features = `Я получил вопрос от Заказчика: "${que}". Ответ на вопрос скорее всего содержится в этом тексте: "${helpTxt}". Подготовь ответ, который я просто перешлю Заказчику, без необходимости внесения в него правок.` const apiUrl = 'https://api.openai.com/v1/chat/completions'; const options = { method: 'post', headers: { Authorization: `Bearer ЗДЕСЬ ВАШ ТОКЕН ОТ ОПЕНАИ`, 'Content-Type': 'application/json', }, muteHttpExceptions: true, payload: JSON.stringify( { "model": "gpt-4", "messages": [{ "role": "user", "content": features, }], "temperature": 0.7 }), }; const response = UrlFetchApp.fetch(apiUrl, options); const content = response.getContentText(); console.log(content) let json = JSON.parse(content) if (json.error) { return json.error.message } return json.choices[0].message.content }

В следующей заметке расскажу как прикрутить эту функцию к боту.

Кому, как и мне, интересно автоматизировать юридические процессы, присоединяйтесь ко мне в телеграме

11
Начать дискуссию