Соединяем AI и реляционную базу данных

от автора

На статью данный текст точно не тянет, скорее это маленькая заметка. Как известно свои дети и свои идеи они всегда самые лучшие. Я давно работаю с реляционными базами и очень люблю язык SQL за его формализм, скорее всего из-за этой моей профдеформации и родилась эта мысль. На работе ко мне иногда обращались сделать выгрузку в CSV файл из базы для обучения моделей или анализа данных, и я подумал, а зачем выгружать данные, а потом иногда загружать обратно результат в базу. Почему не сделать так что бы результат запроса сразу отправлялся на обработку в AI и затем выдавался ответ на запрос. Нам всего лишь нужна SQL функция которая берет результат запроса, заворочает его в вызов к модели, а потом выдает результат. Понятно, что серебряной пули нет и данный подход не везде будет работать, например, такой подход не подразумевает асинхронность, а значит если нужна высокая производительность, то данный подход не очень подходит, с другой стороны сейчас запросы к AI не дёшевы и если вы пошлете 100 запросов в секунду, не дождавшись ответа на предыдущие то скорее всего получите ошибку. Я думаю в будущем это будет стандартная функции в базах данных.

Теперь рассмотрим простейшую реализацию данной функции. Под рукой был PostgreSQL, но можно реализовать это и для ORACLEили других баз. Для этого нам понадобится расширение. В качестве AI будем использовать Groq. Первое что нам надо это получить API ключ. Сама функция очень простая.

CREATE OR REPLACE FUNCTION ai.completions( role_user text, role_sys text DEFAULT '')     RETURNS jsonb     LANGUAGE 'plpgsql' AS $BODY$ DECLARE url text = 'https://api.groq.com/openai/v1/chat/completions';   j text;   req http_request;   key_header http_header;   http_status integer;   error text; BEGIN     key_header.field = 'Authorization';     key_header.value = 'Bearer ' ||  ‘API key’;     req.method = 'POST';     req.headers= array[key_header];     req.uri = url;     req.content_type = 'application/json';     req.content = format('{     "model": "meta-llama/llama-4-scout-17b-16e-instruct",     "messages": [       {"role": "system", "content": "%s"},       {"role": "user", "content": "%s"}     ],     "temperature": 0.7   }', role_sys, role_user);  SELECT status, content INTO http_status, j FROM http(req); IF (http_status != 200) THEN RAISE EXCEPTION  USING  ERRCODE = 'AI002', MESSAGE = j; END IF; RETURN j::jsonb; END; $BODY$; 

Примеры работы, перед запуском советую установить следующие параметры

select http_set_curlopt('CURLOPT_CONNECTTIMEOUT', '10'); select http_set_curlopt('CURLOPT_TIMEOUT', '10');
select * from  ai.completions('сколько будет 2 + 2', 'ты математик, верни только ответ') t

Результат

{   "id": "chatcmpl-ac97506b-0b35-4e4d-bc82-3142fd0d3bc3",   "model": "meta-llama/llama-4-scout-17b-16e-instruct",   "usage": {     "queue_time": 0.09607076599999999,     "total_time": 0.008472493,     "prompt_time": 0.003623623,     "total_tokens": 30,     "prompt_tokens": 28,     "completion_time": 0.00484887,     "completion_tokens": 2   },   "object": "chat.completion",   "x_groq": {     "id": "req_01k0vr86dtfz1rfh86ba6ztd7d"   },   "choices": [     {       "index": 0,       "message": {         "role": "assistant",         "content": "4"       },       "logprobs": null,       "finish_reason": "stop"     }   ],   "created": 1753278061,   "service_tier": "on_demand",   "usage_breakdown": null,   "system_fingerprint": "fp_37da608fc1" }
select * from  ai.completions('Стоит ли сейчас шортить биткоин?',      'ты профессиональный помощник по криптотрейдингу. Отвечай кратко и точно.') t

Результат

{   "id": "chatcmpl-1f78c32f-8ae9-4134-a90d-748fd1b507c2",   "model": "meta-llama/llama-4-scout-17b-16e-instruct",   "usage": {     "queue_time": 0.412265067,     "total_time": 0.062087713,     "prompt_time": 0.003936061,     "total_tokens": 70,     "prompt_tokens": 45,     "completion_time": 0.058151652,     "completion_tokens": 25   },   "object": "chat.completion",   "x_groq": {     "id": "req_01k0vrhw0yexxavgh5p6m0z507"   },   "choices": [     {       "index": 0,       "message": {         "role": "assistant",         "content": "Нет, сейчас не лучший момент для шорта биткоина. Лучше дождаться подтверждения нисходящего тренда."       },       "logprobs": null,       "finish_reason": "stop"     }   ],   "created": 1753278378,   "service_tier": "on_demand",   "usage_breakdown": null,   "system_fingerprint": "fp_79da0e0073" }
select   ai.completions('Сосчитай сумму чисел в массиве '                  || string_agg(d.price::text, ','), 'ты математик')   from ( select t.price     from crypto_bot2.binance_data t where t.pair='BTCUSDT'    order by t.t_date desc limit 10) d

Результат

{   "id": "chatcmpl-dc5f9394-518f-4011-9494-0a8e88d5aff9",   "model": "meta-llama/llama-4-scout-17b-16e-instruct",   "usage": {     "queue_time": 1.975420253,     "total_time": 0.474911567,     "prompt_time": 0.006071319,     "total_tokens": 262,     "prompt_tokens": 76,     "completion_time": 0.468840248,     "completion_tokens": 186   },   "object": "chat.completion",   "x_groq": {     "id": "req_01k0vrn55ef6rbw3ztzkk08p2v"   },   "choices": [     {       "index": 0,       "message": {         "role": "assistant",         "content": "Чтобы найти сумму чисел в данном массиве, я сложу все числа:\n\n117763.12 + 117789.74 = 235552.86\n235552.86 + 117735.53 = 353288.39\n353288.39 + 117718.625 = 471006.015\n471006.015 + 117725.19 = 588731.205\n588731.205 + 117674.25 = 706405.455\n706405.455 + 117656.75 = 824062.205\n824062.205 + 117646.13 = 941708.335\n941708.335 + 117646.086 = 1059354.421\n1059354.421 + 117650.914 = 1177005.335\n\nСумма чисел в данном массиве равна: 1177005.335"       },       "logprobs": null,       "finish_reason": "stop"     }   ],   "created": 1753278487,   "service_tier": "on_demand",   "usage_breakdown": null,   "system_fingerprint": "fp_37da608fc1" }

Где мы можем использовать данный подход

Наверное, эта часть самая сложная. Это как Raspberry pi или Arduino, отличные игрушки, но где их применить в реальной жизни. Я думаю вот несколько примеров где пригодится данный подход

  1. У нас есть старая система и мы хотим без переделки добавить AI в нее, и анализировать наши данные и рисовать графики. К старой системе прилагаются старые программисты, которым работать с запросами гораздо проще чем делать вызовы REST API

  2. Генерация тестовых данных

  3. Для торговых ботов подтверждение сигналов тех анализа, новостными сигналами

  4. Разбор больших текстов и заполнение нужных полей в зависимости от содержимого текста.

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

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


ссылка на оригинал статьи https://habr.com/ru/articles/930406/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *