На статью данный текст точно не тянет, скорее это маленькая заметка. Как известно свои дети и свои идеи они всегда самые лучшие. Я давно работаю с реляционными базами и очень люблю язык 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, отличные игрушки, но где их применить в реальной жизни. Я думаю вот несколько примеров где пригодится данный подход
У нас есть старая система и мы хотим без переделки добавить AI в нее, и анализировать наши данные и рисовать графики. К старой системе прилагаются старые программисты, которым работать с запросами гораздо проще чем делать вызовы REST API
Генерация тестовых данных
Для торговых ботов подтверждение сигналов тех анализа, новостными сигналами
Разбор больших текстов и заполнение нужных полей в зависимости от содержимого текста.
В медицинских базах или базах автосервиса и тому подобное, постановка диагноза на основе жалоб клиента и автоматическое заполнение нужных полей.
Понятно, что реализация может быть лучше и на другом языке, можно реализовать функцию построения рисунка или графика на основе данных из базы. Это всего лишь пример. Наверное, это все, чем я хотел с вами поделится, пишите, что думаете об этой идеи, сильно прошу не бить.