Соединяем AI и реляционную базу данных. ai.. ai. oracle.. ai. oracle. PostgreSQL.. ai. oracle. PostgreSQL. SQL.. ai. oracle. PostgreSQL. SQL. ИИ.. ai. oracle. PostgreSQL. SQL. ИИ. искусственный интеллект.. ai. oracle. PostgreSQL. SQL. ИИ. искусственный интеллект. искуственный интеллект.

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

Теперь рассмотрим простейшую реализацию данной функции. Под рукой был PostgreSQL, но можно реализовать это и для ORACLEили других баз. Для этого нам понадобится расширение https://github.com/pramsey/pgsql-http . В качестве 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": "Чтобы найти сумму чисел в данном массиве, я сложу все числа:nn117763.12 + 117789.74 = 235552.86n235552.86 + 117735.53 = 353288.39n353288.39 + 117718.625 = 471006.015n471006.015 + 117725.19 = 588731.205n588731.205 + 117674.25 = 706405.455n706405.455 + 117656.75 = 824062.205n824062.205 + 117646.13 = 941708.335n941708.335 + 117646.086 = 1059354.421n1059354.421 + 117650.914 = 1177005.335nnСумма чисел в данном массиве равна: 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.      В медицинских базах или базах автосервиса и тому подобное, постановка диагноза на основе жалоб клиента и автоматическое заполнение нужных полей.

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

Автор: antokols

Источник

Rambler's Top100