Перейти к основному контенту
Tech Path Finder
КурсыИнтервьюКод-ревьюБлог
Tech Path Finder

Персонализированный путеводитель в IT. Квизы, мок-интервью, код ревью и аналитика прогресса.

@potapov_me

Платформа

  • Курсы
  • Прогресс
  • Мок-интервью
  • Код ревью
  • Живое ревью с ИИ
  • Тренажёр переговоров
  • Закладки

Контент

  • Блог
  • Главная
  • Обратная связь

Компания

  • О проекте
  • Тарифы
  • Условия использования
  • Конфиденциальность
  • Согласие на обработку данных
  • Cookie
  • Реквизиты

Аккаунт

  • Войти
  • Зарегистрироваться
  • Профиль

© 2026 Tech Path Finder. Все права защищены.

·ИП Потапов К.С.·Политика конфиденциальности·
Сделано с ❤️ в России
  1. Интеграция с LLM
llm_integration

Интеграция с LLM

Подключение LLM: OpenAI, Anthropic, локальные модели через OpenRouter и Ollama

Интеграция с LLM

Embedding нашёл контекст. Теперь LLM превращает его в ответ.

#Роль LLM в RAG-системе

В RAG-пайплайне LLM — это генератор ответов. После того как retrieval нашёл релевантные чанки, LLM получает промпт с контекстом и вопросом, и создаёт текстовый ответ.

Качество LLM критично: даже с отличным контекстом слабая модель может дать плохой ответ. И наоборот — сильная модель с плохим промптом тоже ошибётся.

В этой теме мы разберём, как подключать разные LLM-провайдеры к RAG-системе.

#OpenAI API

OpenAI — самый популярный провайдер LLM. Модели GPT-4o, GPT-4o-mini, o1 и другие.

#Установка и настройка

from openai import OpenAI # Клиент читает ключ из переменной окружения OPENAI_API_KEY client = OpenAI() # Или явно указываем ключ client = OpenAI(api_key="sk-your-key-here")

Ключ API лучше хранить в переменных окружения, а не в коде:

export OPENAI_API_KEY="sk-your-key-here"
import os from openai import OpenAI client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])

#Chat Completions API

response = client.chat.completions.create( model="gpt-4o-mini", messages=[ {"role": "system", "content": "Ты помощник, который отвечает на вопросы по документам компании."}, {"role": "user", "content": "Как оформить отпуск?"} ], temperature=0.3, max_tokens=500 ) answer = response.choices[0].message.content print(answer)

Параметры:

  • model — название модели. gpt-4o-mini дешевле и быстрее, gpt-4o качественнее
  • messages — список сообщений. role: system (инструкция), user (вопрос), assistant (предыдущий ответ)
  • temperature — креативность: 0 = детерминированный ответ, 1 = разнообразный. Для RAG обычно 0.1–0.3
  • max_tokens — максимальная длина ответа. 500 токенов ≈ 350–400 слов

#RAG-промпт с OpenAI

def rag_query(question, context_chunks, client): """RAG-запрос с контекстом.""" context = "\n\n".join(context_chunks) prompt = f"""Ответь на вопрос, используя следующий контекст из документов: {context} Вопрос: {question} Если в контексте нет информации для ответа, скажи «Информация не найдена в документах».""" response = client.chat.completions.create( model="gpt-4o-mini", messages=[ {"role": "system", "content": "Ты помощник по документам компании. Отвечай только на основе предоставленного контекста."}, {"role": "user", "content": prompt} ], temperature=0.1, max_tokens=500 ) return response.choices[0].message.content # Использование context = [ "Отпуск оформляется через HR-портал. Заявление подаётся за 2 недели.", "Для международных отпусков процедура занимает до 4 недель." ] answer = rag_query("Как оформить международный отпуск?", context, client) print(answer)

#Anthropic Claude API

Anthropic — альтернатива OpenAI с моделями Claude 3.5 Sonnet, Claude 3 Opus, Claude 3 Haiku.

#Установка

pip install anthropic

#Messages API

import anthropic client = anthropic.Anthropic(api_key="sk-ant-your-key") message = client.messages.create( model="claude-3-haiku-20240307", max_tokens=500, system="Ты помощник по документам компании. Отвечай только на основе контекста.", messages=[ {"role": "user", "content": "Как оформить отпуск?"} ] ) answer = message.content[0].text print(answer)

Ключевое отличие от OpenAI: системный промпт передаётся отдельным параметром system, а не в списке сообщений.

#RAG с Claude

def rag_claude(question, context_chunks, client): context = "\n\n".join(context_chunks) prompt = f"""Контекст из документов: {context} Вопрос: {question} Ответь на вопрос, используя контекст. Если информации нет в контексте, скажи «Информация не найдена».""" message = client.messages.create( model="claude-3-haiku-20240307", max_tokens=500, system="Ты — эксперт по внутренним документам компании.", messages=[{"role": "user", "content": prompt}] ) return message.content[0].text

Claude часто лучше понимает длинные контексты и реже «галлюцинирует» — для RAG это важно.

#Локальные модели через Ollama

Ollama — инструмент для запуска LLM локально. Не нужен API-ключ, данные не уходят с компьютера.

#Установка Ollama

# macOS brew install ollama # Запускаем сервер ollama serve & # Скачиваем модель ollama pull llama3.2

#Python-клиент

pip install ollama
import ollama response = ollama.chat( model="llama3.2", messages=[ {"role": "user", "content": "Как оформить отпуск?"} ] ) answer = response["message"]["content"] print(answer)

#RAG с Ollama

def rag_ollama(question, context_chunks): context = "\n\n".join(context_chunks) prompt = f"""Контекст: {context} Вопрос: {question} Ответь на основе контекста. Если информации нет, скажи «Информация не найдена».""" response = ollama.chat( model="llama3.2", messages=[{"role": "user", "content": prompt}], options={"temperature": 0.1} ) return response["message"]["content"]

Плюсы Ollama: бесплатно, приватно, оффлайн. Минусы: локальные модели уступают GPT-4/Claude по качеству, особенно для русского языка.

#OpenRouter: единый API для множества моделей

OpenRouter — агрегатор LLM-провайдеров. Один API-ключ даёт доступ к десяткам моделей от разных компаний.

#Установка

pip install openai # OpenRouter совместим с OpenAI SDK

#Настройка

from openai import OpenAI client = OpenAI( base_url="https://openrouter.ai/api/v1", api_key="sk-or-your-key" ) response = client.chat.completions.create( model="anthropic/claude-3.5-sonnet", # или openai/gpt-4o, или meta-llama/llama-3.1-70b messages=[ {"role": "user", "content": "Как оформить отпуск?"} ] ) print(response.choices[0].message.content)

Формат model — провайдер/модель. Доступные модели можно посмотреть на openrouter.ai/models.

#RAG через OpenRouter

def rag_openrouter(question, context_chunks, model="anthropic/claude-3-haiku"): context = "\n\n".join(context_chunks) prompt = f"""Контекст: {context} Вопрос: {question} Ответь на основе контекста.""" client = OpenAI( base_url="https://openrouter.ai/api/v1", api_key="sk-or-your-key" ) response = client.chat.completions.create( model=model, messages=[ {"role": "system", "content": "Помощник по документам. Отвечай только по контексту."}, {"role": "user", "content": prompt} ], temperature=0.1 ) return response.choices[0].message.content

#Streaming ответов

По умолчанию LLM ждёт полный ответ и возвращает его целиком. Для длинных ответов это создаёт задержку. Streaming позволяет получать ответ по частям.

#OpenAI streaming

stream = client.chat.completions.create( model="gpt-4o-mini", messages=[{"role": "user", "content": "Расскажи подробно про процедуру отпуска"}], stream=True # Включаем стриминг ) full_response = "" for chunk in stream: if chunk.choices[0].delta.content: token = chunk.choices[0].delta.content full_response += token print(token, end="", flush=True) # Печатаем каждый токен сразу print(f"\n\nПолная длина: {len(full_response)} символов")

#Ollama streaming

stream = ollama.chat( model="llama3.2", messages=[{"role": "user", "content": "Расскажи про отпуск"}], stream=True ) full_response = "" for chunk in stream: token = chunk["message"]["content"] full_response += token print(token, end="", flush=True)

#Обработка ошибок и повторные попытки

API-вызовы могут падать: сеть, лимиты, неверный ключ. Обработка ошибок и retries обязательны для надёжной RAG-системы.

import time from openai import OpenAI, APIError def llm_with_retry(prompt, max_retries=3, delay=2): """Вызов LLM с повторными попытками при ошибке.""" client = OpenAI() for attempt in range(max_retries): try: response = client.chat.completions.create( model="gpt-4o-mini", messages=[{"role": "user", "content": prompt}], temperature=0.1, max_tokens=500 ) return response.choices[0].message.content except APIError as e: print(f"Попытка {attempt + 1} не удалась: {e}") if attempt < max_retries - 1: time.sleep(delay * (2 ** attempt)) # Экспоненциальная задержка else: raise # Пробрасываем ошибку после всех попыток result = llm_with_retry("Как оформить отпуск?") print(result)

Экспоненциальная задержка: 2с → 4с → 8с. Это стандартный паттерн для работы с API.

#Управление стоимостью

LLM API оплачивается по токенам. 1 токен ≈ 4 символа английского текста (для русского — чуть меньше).

def estimate_cost(input_tokens, output_tokens, model="gpt-4o-mini"): """Оценивает стоимость запроса.""" prices = { "gpt-4o-mini": {"input": 0.15, "output": 0.60}, # $/1M токенов "gpt-4o": {"input": 2.50, "output": 10.00}, "claude-3-haiku": {"input": 0.25, "output": 1.25}, } price = prices.get(model, {"input": 1.0, "output": 2.0}) input_cost = (input_tokens / 1_000_000) * price["input"] output_cost = (output_tokens / 1_000_000) * price["output"] return input_cost + output_cost # Типичный RAG-запрос: 2000 токенов контекста + 500 токенов ответа cost = estimate_cost(2000, 500, "gpt-4o-mini") print(f"Стоимость одного запроса: ${cost:.6f}") print(f"Стоимость 1000 запросов: ${cost * 1000:.4f}")

Для gpt-4o-mini один RAG-запрос стоит доли цента. Для gpt-4o — заметно дороже. Выбор модели зависит от бюджета и требований к качеству.

Далее: Создание промптов