Запрос к нейросети в Power Query
Сегодня будем делать простую, но классную штуку - научим Power Query выполнять запросы к нейросетям для обработки и анализа загруженных данных. Делать это будем на примере DeepSeek - она в России пока ещё работает без VPN, стоит недорого, а по качеству отстаёт от флагманов в лице OpenAI или Claude не так сильно. Кроме того, весь разобранный далее процесс и код подключения можно легко адаптировать к любой другой нейросети - принципы у всех плюс-минус одинаковые.
Для примера вот такую таблицу с криво и неполно записанными адресами и предположим, что нам необходимо извлечь из них в отдельный столбец только город:

Обратите внимание, насколько у нас тут всё запущено: Санкт-Петербург в нескольких вариантах, город может быть в начале адреса или в конце, с "г." и без, а где-то есть только почтовый индекс. Плюс некоторые названия написаны не полностью (В.Новгород) или с ошибками (Чилябинск).
Подобная задача практически невыполнима встроенными средствами Power Query (если только у вас нет полного справочника со всеми вариантами написания всех городов), но для ИИ это будет вполне по силам.
Рассмотрим весь процесс по шагам.
Шаг 1. Получаем API-ключ ИИ
Тут всё стандартно.
- Регистрируемся на сайте DeepSeek, если вы ещё этого не сделали.
- В личном кабинете в разделе Top up пополняем аккаунт хотя бы на 2-5$, чтобы иметь возможность использовать запросы по API. Для пополнения потребуется нероссийская банковская карта. Если её нет, то можно выпустить виртуальную карту или воспользоваться услугами посредников или специализированных платёжных сервисов.
- Там же в разделе API keys создаем API-ключ - длинную буквенно-цифровую последовательность, выполняющую роль вашего идентификатора при обращении к нейросети. Ключ желательно скопировать и сохранить где-нибудь в надёжном месте, т.к. показывается он вам только единожды при создании, а потом будет скрыт. Скомпрометированный ключ, который случайно узнал кто-то посторонний, всегда можно удалить, а вместо него создать новый.
- В разделе Usage в будущем можно контролировать расход средств и остаток на счёте.
Шаг 2. Пишем M-функцию запроса к нейросети в Power Query
В языке М, который работает "под капотом" у Power Query содержится более 700 встроенных функций, но готовой функции запроса к нейросетям там пока нет. Так что нам придётся написать её самостоятельно.
Чтобы начать "с чистого листа" в Microsoft Excel выбираем команды Данные - Получить данные - Из других источников - Пустой запрос (Data - Get data - From other sources - Blank query). Затем на вкладке Просмотр жмём на кнопку Расширенный редактор (View - Advanced Editor), чтобы перейти к исходному коду запроса на языке М. Стираем всё, что увидим в открывшемся окне и копируем-вставляем туда следующий М-код:
(Instruction, SourceData, Temp) =>
let
apiKey = "ТУТ ДОЛЖЕН БЫТЬ ВАШ API-КЛЮЧ",
//формируем запрос
prompt =
Json.FromValue(
[
model = "deepseek-chat",
messages = {
[ role = "system", content = Instruction ],
[ role = "user", content = SourceData ]
},
temperature = Temp
]
),
//делаем запрос к ИИ и получаем ответ
response =
Json.Document(
Web.Contents(
"https://api.deepseek.com/chat/completions",
[
Headers = [ #"Content-Type" = "application/json", #"Authorization" = "Bearer " & apiKey ],
Content = prompt
]
)
),
result = response[choices]{0}[message][content]
in
result
Убеждаемся в нижней части окна, что не найдено ошибок и жмём на кнопку Готово. После этого можно назвать созданный запрос (точнее говоря, уже функцию) любым подходящим образом - например, AskDeepSeek. При необходимости к исходному коду функции всегда можно будет вернуться, нажав на ту же кнопку Расширенный редактор (Advanced Editor).
Если вам неохота разбираться с механикой его работы, то можете сразу переходить к следующему шагу - применению этого кода к нашим данным. Если же вам интересно, как, на самом деле, это работает, то давайте поясню.
Технически, этот М-код - это не обыкновенный запрос Power Query (который надо вручную обновлять), а функция. От запроса она отличается тем, что получает на входе какие-то данные в качестве аргументов, что-то с ними делает и возвращает результат своей работы нам обратно. Т.е. всё примерно также, как у привычных нам экселевских функций.
В данном случае у этой функции будет три аргумента:
- Instruction - инструкция, которую мы даём ИИ (например, "извлеки название города из адреса")
- SourceData - исходные данные, которые мы передаём ИИ на обработку
- Temperature - необязательный аргумент, задающий температуру запроса - дробное число в интервале 0..2, определяющее степень креативности ИИ-модели (0 - сухо и чётко, 2 - графоманский бред )
В начале кода мы задаём в переменной apiKey наш ключ API, полученный на сайте модели.
После этого в переменной prompt с помощью М-функции Json.FromValue мы формируем запрос для нейросети в формате JSON, где задаются все необходимые исходные данные и параметры генерации: выбранная модель, инструкция, исходные данные на обработку и температура запроса.
Затем при помощи М-функции Web.Contents мы выполняем веб-запрос к ИИ-модели, используя наш ключ из переменной apiKey и собранный запрос с параметрами из переменной prompt.
ИИ возвращает ответ также в формате JSON, который мы читаем с помощью функции Json.Document и помещаем в переменную response. Кроме, собственно, ответа там будет содержаться много сопутствующей технической информации, так что далее мы выуживаем только текстовый ответ модели и помещаем его в переменную result. Её затем и возвращаем как результат всей функции после оператора in.
Я намеренно сделал этот код максимально простым, чтобы вы ухватили суть. При желании, в него, конечно же, можно внести массу улучшений и украшений: добавить обработку ошибок от сервера, сохранять API-ключ не открытым текстом в коде, а брать из внешнего txt-файла и т.д. Можете заняться этим потом при желании :)
Шаг 3. Применяем функцию
Осталось самое простое и интересное - применить созданную функцию для решения нашей рабочей задачи.
Конвертируем исходную таблицу с кривыми адресами в динамическую "умную" таблицу сочетанием клавиш Ctrl+T и загружаем в Power Query командой Данные - Из таблицы/диапазона или щёлкнув по таблице правой кнопкой мыши - Получить данные из таблицы/диапазона.
Затем применяем нашу функцию, выбрав на вкладке Добавление столбца команду Вызвать настраиваемую функцию (Add column - Invoke Custom function). В открывшемся окне задаём её аргументы:

После нажатия на OK наш Power Query ненадолго задумается. Или надолго - зависит от объема исходных данных. У меня уходило около 1 сек на каждую строку в среднем. Но, рано или поздно, выдаст нам результаты ИИ-запроса в новом столбце:

Красота :)
Другие нейросети
При желании приведённый выше код можно легко адаптировать под другие нейросети - большинство из них сейчас поддерживают единый стандарт API-запроса, который мы использовали выше. Например, для запроса не к DeepSeek, а к OpenAI ChatGPT в коде необходимо будет поменять:
- адрес подключения в первом аргументе функции Web.Contents на https://api.openai.com/v1/chat/completions
- название модели в переменной prompt - например, на "gpt-4o-mini"
- API-ключ в переменной apiKey
Дисклеймер
И пожалуйста не забывайте два важных момента:
- Любая нейросеть может ошибаться и выдумывать факты (особенно при высоких значениях температуры), поэтому внимательно проверяйте полученные результаты.
- Используя любую нейросеть, вы отправляете в каждом запросе свои данные на её сервер для обработки. Если это чувствительная информация (персональные или корпоративные данные и т.п.), то лучше рассмотреть вариант с развёртыванием локальной нейросети на вашем ПК (например, с помощью LM Studio или Ollama) для решения подобных задач.
Ссылки по теме
- Столбец из примеров - встроенный ИИ в Power Query
- Нечёткий текстовый поиск в Power Query
- Используем ChatGPT в Microsoft Excel
(Instruction, SourceData, Temp) => let apiKey = "Ваш ключ", baseUrl = [url=https://llm.globalapi.ru/v1]"https/llm.globalapi.ru/v1"[/url], // Формируем тело запроса с правильной структурой requestBody = Text.FromBinary(Json.FromValue([ model = "deepseek-chat", messages = { [role = "system", content = Instruction], [role = "user", content = SourceData] }, temperature = Temp, stream = false ]), // Отправляем запрос response = Json.Document( Web.Contents( baseUrl, [ Headers = [ #"Content-Type" = "application/json", #"Authorization" = "Bearer " & apiKey ], Content = Text.ToBinary(requestBody), RelativePath = "/chat/completions" ] ) ), // Извлекаем ответ result = response[choices]{0}[message][content] in resultВставляю Верный код Дениса, так как у него при копировании кода в двух местах (двоеточие и слеш, а также скобка) автозаменились на эмодзи:
(Instruction, SourceData, Temp) =>
let
apiKey = "Ваш Ключ с сайта GlobalAPI",
baseUrl = "https://llm.globalapi.ru/v1",
// Формируем тело запроса с правильной структурой
requestBody = Text.FromBinary(
Json.FromValue(
[
model = "deepseek-chat",
messages = {
[role = "system", content = Instruction],
[role = "user", content = SourceData]
},
temperature = Temp,
stream = false
]
) ),
// Отправляем запрос
response =
Json.Document(
Web.Contents(
baseUrl,
[
Headers = [
#"Content-Type" = "application/json",
#"Authorization" = "Bearer " & apiKey
],
Content = Text.ToBinary(requestBody),
RelativePath = "/chat/completions"
]
)
),
// Извлекаем ответ
result = response[choices]{0}[message][content]
in
result