Онлайн час в Google Meet
Лого на 91. НЕГ „Проф. Константин Гълъбов“

12. клас · Избираем модул · Урок 29

Проект: AI компонент и интерфейс

Цялата верига от входа на потребителя през промпт, извикване и проверка до запис и показване; ключът извън кода, грешките, които не свалят приложението, и най-простият ползваем интерфейс.

Целта на часа

Базата от миналия час работи. Днес потребителят въвежда нещо, то минава през модела, отговорът се проверява, записва се в базата и се показва. Грешките не свалят приложението. Това е критерият „AI компонент“ — 25% — и половината от „Интерфейс и тестване“.

ГотовоКак се проверява
Функция ai_funkcia(vhod)връща резултат или разбираема грешка; никога не хвърля изключение навън
Ключне се вижда в нито една клетка, файл или екранна снимка
Записвсяко извикване оставя ред в служебната таблица — и успешното, и отказаното
Интерфейссъученик от друг екип го ползва без указания
Сценарийпет входа за защитата, единият нарочно се проваля

Цялата верига

ВХОДвъпрос, обява, снимкаПРОМПТсхема / парчета / правилаИЗВИКВАНЕмодел, t = 0ПРОВЕРКАSELECT? JSON? източник?ИЗХОДзапис + показванепри неуспешна проверка: разбираемо съобщение, без изпълнение, записва се и товаКлючът за API е извън кода — в userdata на Colab или в променлива на средата
Петте стъпки са едни и същи за всяка тема — сменя се само какво влиза в промпта и какво се проверява.

Веригата вече сте я строили на части: извикване (урок 19), JSON по схема (урок 20), „разговор с базата“ (урок 23), RAG (урок 26). Днес я сглобявате в една функция, чието име е без значение, а договорът — не: приема входа на потребителя и връща резултат или текст на грешка, но никога не гърми.

Вид функцияКакво влиза в промптаКакво се проверява преди изхода
разговор с базатасхемата на изгледа, правило „само една заявка SELECT“, примерен въпрос → заявказапочва със SELECT; няма DROP/DELETE/UPDATE; изпълнява се на връзка само за четене; до 50 реда
извличане на JSONJSON схема с типове и задължителни полета, текстът на обявата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 — бутонът се изключва, докато чака (иначе двойни заявки).
  • Прост уеб формуляр — само ако някой в екипа вече го умее. Не е плюс в оценката.

Четирите функционални изисквания

  1. Показва, че работи, докато чака („Питам модела…“).
  2. Показва на какво стъпва резултатът — заявката, извлечения JSON, източника на парчето.
  3. При грешка показва разбираемо съобщение, а не изключение.
  4. Не пуска празен вход и не пуска втора заявка, докато първата не свърши.

Демонстрационен сценарий

Подгответе точно пет входа за защитата и ги запишете с очаквания резултат:

  1. лесен — показва, че работи
  2. с други думи или синоним — показва, че моделът не търси по букви
  3. без отговор в базата или в документа — показва честното „не знам“
  4. граничен — празен вход, дълъг вход, число извън обхвата
  5. труден, който се проваля — показва, че познавате границите

Какво трябва да запомниш

  • AI функцията е една функция: вход → промпт → извикване → проверка → изход; връща резултат или грешка, никога не гърми.
  • Проверката преди изхода е задължителна — моделът дава правдоподобен, не верен отговор.
  • Ключът е в userdata на Colab или в променлива на средата; търсене по „AIza“ преди всяко споделяне.
  • Шестте типични счупвания имат разбираемо съобщение и се записват в служебната таблица.
  • Най-простият ползваем интерфейс с четирите функционални изисквания; оформлението не носи точки.
  • Пет входа за защитата, единият нарочно се проваля; екранни снимки за резерва.