Часть 1. Ответы
- Перегрузка сервера (медленный ответ), превышение лимита запросов (rate limit), нестабильная сеть.
- Таймаут прерывает ожидание, если сервер не ответил за N секунд. Без него запрос может «висеть» бесконечно, и программа зависнет.
- 500 — ошибка сервера, 403 — неверный ключ/нет доступа, 429 — превышен лимит. Повторять бессмысленно 403 (ключ не починится сам).
- Эмбеддинг — числовой вектор текста. Тексты похожи, если их векторы близки (малое расстояние / большой косинус).
- Поиск по словам ищет совпадения символов/слов; семантический — близость смысла, находит синонимы и перефразировки без общих слов.
Часть 2. Эталон кода
Задание 1 — устойчивый запрос
# resilient.py
import time, os
from tenacity import retry, stop_after_attempt, wait_exponential
from google import genai
from google.genai import types
from dotenv import load_dotenv
load_dotenv()
client = genai.Client(
api_key=os.getenv("GEMINI_API_KEY"),
http_options=types.HttpOptions(timeout=10000), # 10 c
)
@retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=2, max=10))
def ask(prompt):
time.sleep(0.3)
r = client.models.generate_content(model="gemini-2.0-flash", contents=[prompt])
return r.text
print(ask("Объясни, что такое rate limit, в 2 предложениях."))
Задание 2 — эмбеддинги
# embed.py
import os
import numpy as np
from google import genai
from dotenv import load_dotenv
load_dotenv()
client = genai.Client(api_key=os.getenv("GEMINI_API_KEY"))
def get_embedding(text):
r = client.models.embed_content(model="text-embedding-004", contents=text)
return np.array(r.embeddings[0].values)
v1 = get_embedding("Я люблю программирование.")
v2 = get_embedding("Кодинг – это моё хобби.")
print("Размерность:", v1.shape) # (768,)
Задание 3 — семантический поиск (FAISS)
# search.py (продолжение embed.py)
import faiss
texts = [
"Кошки любят рыбу и мясо",
"Основной рацион кошек — это белок",
"Чем кормить котёнка?",
"Собака играет в парке",
"Спелый ананас полон витаминов",
]
emb = np.array([get_embedding(t) for t in texts])
index = faiss.IndexFlatL2(emb.shape[1])
index.add(emb)
q = get_embedding("Питание кошек").reshape(1, -1)
D, I = index.search(q, 2)
print([texts[i] for i in I[0]])
Часть 3. Со звёздочкой — косинусная близость
# cosine_search.py (фрагмент)
emb = np.array([get_embedding(t) for t in texts]).astype("float32")
faiss.normalize_L2(emb) # нормализуем векторы
index = faiss.IndexFlatIP(emb.shape[1]) # скалярное произведение = косинус
index.add(emb)
q = get_embedding("Питание кошек").reshape(1, -1).astype("float32")
faiss.normalize_L2(q)
D, I = index.search(q, 2) # D теперь — косинусная близость (больше = ближе)
print([texts[i] for i in I[0]])
⚠️ Имена моделей/полей и API FAISS зависят от версий; сверяйтесь с документацией.