Skip to content

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 

Repository files navigation

TenderAgent

AI-агент, который помогает малому и среднему бизнесу в Казахстане находить государственные тендеры, оценивать шансы на участие и готовить черновики заявочных документов.

MVP: backend на FastAPI + SQLite, frontend на Next.js (App Router) + TypeScript + Tailwind, AI-слой на Google Gemini API.

Статус источника данных о тендерах: мок-данные

Реальный открытый API госзакупок (ows.goszakup.gov.kz, REST v3 / GraphQL) требует Bearer-токен, который выдаёт АО «Центр электронных финансов» по отдельной заявке — регистрация здесь: https://goszakup.gov.kz/ru/developer/ows_v3. Без токена оба эндпоинта (/v3/trd-buy, /v3/graphql) отвечают 401 Unauthorized (проверено вживую).

Пока токена нет, приложение работает в режиме TENDER_DATA_SOURCE=mock — синхронизация (POST /api/tenders/sync) читает 8 реалистичных тендеров из backend/mock_data/tenders.json, структурно совместимых с полями trd-buy/lots реального API (name_ru, total_sum, end_date, customer_name_ru, ref_subject_type_id и т.д.).

Когда токен будет получен:

  1. Впиши его в backend/.env как GOSZAKUP_API_TOKEN.
  2. Смени TENDER_DATA_SOURCE=mock на TENDER_DATA_SOURCE=live.
  3. Проверь ответ реального /v3/trd-buy и при необходимости поправь маппинг полей в backend/app/services/goszakup_client.py::_fetch_live_tenders — он написан по документации, но не был протестирован вживую (доступ был заблокирован на момент разработки).

Модели данных, роуты и frontend менять не нужно — они не завязаны на источник тендеров.

Стек

  • Backend: Python 3.11+, FastAPI (+ BackgroundTasks для асинхронных AI-задач), SQLAlchemy, SQLite
  • AI: Google Gemini API (google-genai, модель gemini-3.6-flash), structured output через response_schema для JSON-ответов (анализ тендера)
  • Frontend: Next.js (App Router) + TypeScript + Tailwind CSS + shadcn/ui

Исходное ТЗ предполагало Anthropic Claude API — заменено на Google Gemini по явному запросу заказчика в ходе разработки (ключа Anthropic не было под рукой). Вся архитектура AI-слоя (промпты вынесены в app/services/prompts.py, structured output, отдельные сервисы для анализа и генерации черновиков) сохранена, поменялся только провайдер и SDK-вызовы.

AI-анализ и генерация: как это работает под капотом

Анализ тендера и генерация черновика — не синхронные запросы, а фоновые задачи:

  1. POST /api/analysis/{tender_id} / POST /api/drafts/{tender_id} создают запись со статусом queued, сразу возвращают её (202 Accepted) и ставят реальную работу в BackgroundTasks (run_analysis_job / run_draft_job в app/services/).
  2. Фоновая задача сама переводит запись в processing, вызывает Gemini, затем сохраняет результат со статусом completed (или failed + error_message при сбое API).
  3. Фронтенд поллит GET /api/analysis/{id} (или GET /api/drafts/item/{id}) каждые ~700мс (hooks/use-poll.ts), пока статус не станет финальным, и показывает JobProgress — реальный прогресс-бар + скелетоны + сменяющиеся подписи этапов.
  4. Анализ возвращает не просто число, а requirement_checks — Gemini сам разбирает текст требований тендера на пункты и по каждому сверяет профиль компании (✓/✗ + пояснение) — это и есть RequirementChecklist на странице тендера, видимая "логика работы Gemini".

Два bulk-действия демонстрируют, что агент способен работать по всему списку сразу:

  • «Проанализировать все» на дашборде (POST /api/analysis/bulk) — ставит в очередь анализ всех ещё не оценённых (или ранее упавших) тендеров компании; кольца Match Score в таблице заполняются по мере готовности фоновых задач.
  • «Сгенерировать полный пакет» на странице тендера (POST /api/drafts/bulk) — параллельно запускает все 3 типа документов вместо одного за раз.

На бесплатном тарифе Gemini API (gemini-3.6-flash) действует жёсткий лимит запросов в минуту и в день. При его превышении задача просто получает статус failed с понятным сообщением и кнопкой «Повторить» — это штатная обработка ошибки, а не баг.

Структура проекта

tenderagent/
  backend/
    app/
      main.py            # FastAPI app, роуты, CORS
      config.py           # переменные окружения (pydantic-settings)
      database.py          # SQLAlchemy engine/session
      models/              # CompanyProfile, Tender, TenderAnalysis, DraftDocument
      schemas/              # Pydantic-схемы запросов/ответов
      services/
        goszakup_client.py   # синхронизация тендеров (mock/live)
        ai_analysis.py         # AI-анализ + run_analysis_job (фоновая задача)
        draft_generator.py      # генерация черновиков + run_draft_job (фоновая задача)
        prompts.py                # все промпты - редактируются отдельно от логики вызова
        formatting.py               # форматирование Tender/CompanyProfile для промптов
      routers/
        company.py, tenders.py, analysis.py, drafts.py   # bulk-эндпоинты в analysis.py/drafts.py
    tests/
      test_api.py         # pytest: CRUD, синхронизация/дедупликация, async job flow, 404-пути
    mock_data/
      tenders.json        # 8 реалистичных тендеров для режима mock
    requirements.txt
    .env.example
  frontend/
    src/
      app/
        tenders/           # дашборд: Match Score кольца, bulk-анализ
        tenders/[id]/        # детали тендера: AI-анализ, requirement checklist, пакет документов
        profile/               # профиль компании
      lib/
        api.ts                # клиент к backend API + TypeScript-типы
        recommendation.ts       # общие лейблы/цвета рекомендаций
      hooks/use-poll.ts       # generic-поллинг фоновых задач
      components/
        ui/                    # shadcn/ui примитивы (button, card, table, select, ...)
        match-score-ring.tsx    # радиальный "meter" для fit_score
        requirement-checklist.tsx  # построчное сопоставление требований и профиля
        job-progress.tsx           # skeleton + progress + этапы во время фоновой задачи
  README.md

Запуск локально

1. Backend

cd backend
python -m venv venv
# Windows:
venv\Scripts\activate
# macOS/Linux:
source venv/bin/activate

pip install -r requirements.txt
cp .env.example .env

Заполни backend/.env:

GEMINI_API_KEY=твой_ключ_gemini      # обязателен для AI-анализа и генерации черновиков
GOSZAKUP_API_TOKEN=                   # оставь пустым, пока нет токена от ЦЭФ
TENDER_DATA_SOURCE=mock               # mock | live
DATABASE_URL=sqlite:///./tenderagent.db

Ключ Gemini можно получить в Google AI Studio: https://aistudio.google.com/apikey

Запуск сервера (порт 8000 указан для примера — если он занят другим процессом, используй --port 8010 или любой свободный и поправь NEXT_PUBLIC_API_URL во frontend/.env.local):

uvicorn app.main:app --reload --port 8000

Проверка: curl http://127.0.0.1:8000/api/health → {"status":"ok"}. Интерактивная документация API: http://127.0.0.1:8000/docs

Тесты:

pytest tests/ -v

2. Frontend

cd frontend
npm install

Создай frontend/.env.local:

NEXT_PUBLIC_API_URL=http://127.0.0.1:8000

(адрес должен совпадать с портом, на котором реально поднят backend)

npm run dev

Открой http://localhost:3000 — редиректит на /tenders.

3. Первый прогон

  1. Открой /profile, заполни профиль компании (сфера деятельности, описание, опыт, документы).
  2. Открой /tenders, нажми «Обновить тендеры» — подтянутся 8 мок-тендеров.
  3. Нажми «Проанализировать все» — фоново запустится анализ сразу всех тендеров, Match Score кольца в таблице заполнятся по мере готовности (поллинг раз в ~1.5с).
  4. Открой любой тендер — увидишь RequirementChecklist: построчное сопоставление требований тендера с профилем компании (✓/✗ + пояснение от Gemini), а не просто число.
  5. В блоке «Пакет документов для подачи» нажми «Сгенерировать полный пакет» — параллельно запустятся все 3 типа документов; либо выбери один тип и «Сгенерировать черновик».

Переменные окружения

Переменная Где Описание
GEMINI_API_KEY backend/.env Ключ Google Gemini API, обязателен для AI-функций
GOSZAKUP_API_TOKEN backend/.env Bearer-токен ows.goszakup.gov.kz, нужен только для TENDER_DATA_SOURCE=live
TENDER_DATA_SOURCE backend/.env mock (по умолчанию) или live
DATABASE_URL backend/.env По умолчанию sqlite:///./tenderagent.db
NEXT_PUBLIC_API_URL frontend/.env.local URL backend API, например http://127.0.0.1:8000

Ограничения MVP (сознательные)

  • Один активный профиль компании, без авторизации/многопользовательского режима.
  • Черновики документов — только текст для копирования, без реальной подачи заявки или ЭЦП.
  • Источник тендеров — мок-данные, пока не получен токен goszakup (см. раздел выше).
  • Рассчитано на 10-20 тендеров для демонстрации, не на промышленный масштаб.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages