YandexGPT в Obsidian TextGenerator
Обновлено 2025-11-28
С первой версии статьи Yandex привел своё API в человеческий вид, а точнее совместимый с OpenAI форматом. Статья стала короче примерно на треть.
Для того чтобы работать с API YandexGPT необходимо быть зарегистрированным в Yandex Cloud и иметь действующий платежный аккаунт.
Для авторизации в API потребуется либо IAM токен либо API ключ.
Obsidian
- Установить плагин TextGenerator
- Выбрать
Provider Profile-Customили клонировать его нажав+
- В поле
Endpointуказатьhttps://llm.api.cloud.yandex.net/v1/chat/completions - В поле
API Keyуказать либо IAM_TOKEN либо API ключ полученный ранее - В поле
modelназвание модели из консоли Yandex типаgpt://b1gjpq05r3ppsou34c7d/yandexgpt-lite/latest.
Advanced mode
Дальнейшие пункты настраиваются после включения переключателя Advanced mode.
- В секции
Headersуказываем следующее при использовании ключа API.
{
"Content-Type": "application/json",
"Authorization": "Api-Key {{api_key}}",
"OpenAI-Project": "b1gjpq05r3ppsou34c7d"
}Или вот так при при использовании IAM токена:
{
"Content-Type": "application/json",
"Authorization": "Bearer {{api_key}}",
"OpenAI-Project": "b1gjpq05r3ppsou34c7d"
}В OpenAI-Project необходимо подставить идентификатор того каталога для которого создавался ключ/токен.
2. Обязательно устанавливаем галочку CORS Bypass
Экспортированный профиль
TextGenerator поддерживает импорт-экспорт профилей. Ниже приведен сохраненный результат описывающий действия выше.
{
id: 'Default (Custom)',
config: {
endpoint: 'https://llm.api.cloud.yandex.net/v1/chat/completions',
custom_header: '{\n "Content-Type": "application/json",\n "authorization": "Api-Key {{api_key}}",\n "OpenAI-Project": "b1gjpq05r3ppsou34c7d"\n\n}',
custom_body: '{\n model: "{{model}}",\n temperature: {{temperature}},\n top_p: {{top_p}},\n frequency_penalty: {{frequency_penalty}},\n presence_penalty: {{presence_penalty}},\n max_tokens: {{max_tokens}},\n n: {{n}},\n stream: {{stream}},\n stop: "{{stop}}",\n messages: {{stringify messages}}\n}',
model: 'gpt://b1gjpq05r3ppsou34c7d/yandexgpt-lite/latest',
sanatization_streaming: '// catch error\nif (res.status >= 300) {\n const err = data?.error?.message || JSON.stringify(data);\n throw err;\n}\nlet resultTexts = [];\nconst lines = this.chunk.split("\\ndata: ");\n\nconst parsedLines = lines\n .map((line) => line.replace(/^data: /, "").trim()) // Remove the "data: " prefix\n .filter((line) => line !== "" && line !== "[DONE]") // Remove empty lines and "[DONE]"\n .map((line) => {\n try {\n return JSON.parse(line)\n } catch { }\n }) // Parse the JSON string\n .filter(Boolean);\n\nfor (const parsedLine of parsedLines) {\n const { choices } = parsedLine;\n const { delta } = choices[0];\n const { content } = delta;\n // Update the UI with the new content\n if (content) {\n resultTexts.push(content);\n }\n}\nreturn resultTexts.join("");',
sanatization_response: "// catch error\nif (res.status >= 300) {\n const err = data?.error?.message || JSON.stringify(data);\n throw err;\n}\n\n// get choices\nconst choices = (data.choices || data).map(c=> c.message);\n\n// the return object should be in the format of \n// { content: string }[] \n// if there's only one response, put it in the array of choices.\nreturn choices;",
frequency_penalty: 0,
presence_penalty: 0.5,
top_p: 1,
api_key: '',
CORSBypass: true,
streamable: false,
},
}