Целта на часа
Базата от миналия час работи. Днес потребителят въвежда нещо, то минава през модела, отговорът се проверява, записва се в базата и се показва. Грешките не свалят приложението. Това е критерият „AI компонент“ — 25% — и половината от „Интерфейс и тестване“.
| Готово | Как се проверява |
|---|---|
| Функция ai_funkcia(vhod) | връща резултат или разбираема грешка; никога не хвърля изключение навън |
| Ключ | не се вижда в нито една клетка, файл или екранна снимка |
| Запис | всяко извикване оставя ред в служебната таблица — и успешното, и отказаното |
| Интерфейс | съученик от друг екип го ползва без указания |
| Сценарий | пет входа за защитата, единият нарочно се проваля |
Цялата верига
Веригата вече сте я строили на части: извикване (урок 19), JSON по схема (урок 20), „разговор с базата“ (урок 23), RAG (урок 26). Днес я сглобявате в една функция, чието име е без значение, а договорът — не: приема входа на потребителя и връща резултат или текст на грешка, но никога не гърми.
| Вид функция | Какво влиза в промпта | Какво се проверява преди изхода |
|---|---|---|
| разговор с базата | схемата на изгледа, правило „само една заявка SELECT“, примерен въпрос → заявка | започва със SELECT; няма DROP/DELETE/UPDATE; изпълнява се на връзка само за четене; до 50 реда |
| извличане на JSON | JSON схема с типове и задължителни полета, текстът на обявата | json.loads минава; задължителните полета ги има; числата са в обхват |
| RAG / помощник по документ | 3–5 най-близки парчета с източник, правило „отговаряй само от текста, иначе кажи „не знам““ | отговорът не е празен; има посочен източник; при ниска близост — „не знам“ без извикване |
| обобщение с графика | резултатът от справката като текст, искане за 3 изречения | числата в текста съвпадат с числата от справката |
Ключът извън кода
Ключът от Google AI Studio е парола. В Colab живее в „Secrets“ (ключето вляво) и се чете с userdata.get("GEMINI_API_KEY"); в C# — в променлива на средата, четена с Environment.GetEnvironmentVariable. Никога в клетка, в низ, в App.config, в екранна снимка.
Ако екипът е на C#
Същото извикване без библиотека — едно HTTP POST към Gemini API с HttpClient. Ключът отива в заглавка, не в адреса.
using System.Net.Http.Json;
using System.Text.Json;
static readonly HttpClient http = new() { Timeout = TimeSpan.FromSeconds(30) };
const string Adres =
"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent";
static async Task<string> PitayAsync(string sistemno, string vhod)
{
string klyuch = Environment.GetEnvironmentVariable("GEMINI_API_KEY")
?? throw new InvalidOperationException("Липсва GEMINI_API_KEY");
var zaqvka = new
{
system_instruction = new { parts = new[] { new { text = sistemno } } },
contents = new[] { new { role = "user", parts = new[] { new { text = vhod } } } },
generationConfig = new { temperature = 0 }
};
using var req = new HttpRequestMessage(HttpMethod.Post, Adres);
req.Headers.Add("x-goog-api-key", klyuch);
req.Content = JsonContent.Create(zaqvka);
using var otg = await http.SendAsync(req);
otg.EnsureSuccessStatusCode();
using var dok = JsonDocument.Parse(await otg.Content.ReadAsStringAsync());
return dok.RootElement.GetProperty("candidates")[0]
.GetProperty("content").GetProperty("parts")[0]
.GetProperty("text").GetString() ?? "";
}Обработка на грешки
На защитата ще се случи поне едно от следните. Приложението трябва да го преживее с разбираемо съобщение, а не с червен текст на изключение.
| Какво се счупва | Какво вижда потребителят | Какво прави програмата |
|---|---|---|
| няма интернет / услугата не отговаря | „Услугата не отговори. Опитайте отново.“ | 2–3 опита с изчакване, после отказ |
| невалиден или липсващ ключ | „Грешка в настройката на приложението.“ | спира при старта, не при първия въпрос |
| изчерпан лимит на безплатното ниво (429) | „Твърде много заявки. Изчакайте минута.“ | изчаква и повтаря веднъж |
| моделът връща текст вместо SQL/JSON | „Не успях да разбера въпроса. Опитайте с други думи.“ | проверката отхвърля, нищо не се изпълнява; записва се |
| заявката гърми в базата | „Заявката не се изпълни.“ + кратка причина | прихваща sqlite3.Error, записва заявката и грешката |
| празен или огромен вход | „Въведете въпрос до 300 знака.“ | проверка преди извикване — без разход |
import time
def pitay_sigurno(vhod, opiti=3):
"""Връща (текст, None) при успех или (None, съобщение) при неуспех."""
for i in range(opiti):
try:
return pitay(vhod), None
except Exception as e:
print(f"опит {i + 1}: {type(e).__name__}")
time.sleep(2 ** i)
return None, "Услугата не отговори. Опитайте отново след малко."Най-простият интерфейс, който върши работа
Не губете часа в оформление. Интерфейсът е ползваем, когато човек, който не е писал кода, може да въведе вход и да разбере резултата. Изберете най-простия вариант, който екипът владее:
- Цикъл с input() в Colab — въпрос, отговор, следващ въпрос; празен ред за изход. Готов за пет минути.
- Форма в Colab — поле с
#@paramи бутон „Run“. Изглежда като приложение, без ред код повече. - Конзолно приложение на C# — същият цикъл с
Console.ReadLine; ако ползвате Windows Forms от модул 4 — бутонът се изключва, докато чака (иначе двойни заявки). - Прост уеб формуляр — само ако някой в екипа вече го умее. Не е плюс в оценката.
Четирите функционални изисквания
- Показва, че работи, докато чака („Питам модела…“).
- Показва на какво стъпва резултатът — заявката, извлечения JSON, източника на парчето.
- При грешка показва разбираемо съобщение, а не изключение.
- Не пуска празен вход и не пуска втора заявка, докато първата не свърши.
Демонстрационен сценарий
Подгответе точно пет входа за защитата и ги запишете с очаквания резултат:
- лесен — показва, че работи
- с други думи или синоним — показва, че моделът не търси по букви
- без отговор в базата или в документа — показва честното „не знам“
- граничен — празен вход, дълъг вход, число извън обхвата
- труден, който се проваля — показва, че познавате границите
Какво трябва да запомниш
- AI функцията е една функция: вход → промпт → извикване → проверка → изход; връща резултат или грешка, никога не гърми.
- Проверката преди изхода е задължителна — моделът дава правдоподобен, не верен отговор.
- Ключът е в userdata на Colab или в променлива на средата; търсене по „AIza“ преди всяко споделяне.
- Шестте типични счупвания имат разбираемо съобщение и се записват в служебната таблица.
- Най-простият ползваем интерфейс с четирите функционални изисквания; оформлението не носи точки.
- Пет входа за защитата, единият нарочно се проваля; екранни снимки за резерва.