AI-генерація заявок на гранти
Грантова заявка — структурований документ із жорсткими вимогами до обсягу, розділів та формулювань. Організації витрачають 40–80 годин на одну заявку у великий фонд. Ми розробили систему, яка скорочує цей час у 5–7 разів без втрати якості. AI не пише заявку за дослідника — це неможливо. AI прискорює чорнову роботу: перекладає технічні описи мовою грантів, перевіряє відповідність вимогам фонду, генерує шаблони розділів і допомагає вибудувати наратив. Замовте впровадження AI-генерації — отримайте готову систему за 3–4 тижні.
За час роботи ми підготували понад 50 заявок для НКО та стартапів — від екологічних проектів до AI-досліджень. Система пройшла перевірку на конкурсах Президентського фонду культурних ініціатив, Сколково та EU Horizon. Результат: середній час заявки впав з 60 до 10 годин, а кількість успішних подач зросла на 40%.
Модулі AI-системи для грантів
Система складається з трьох модулів: аналізатор вимог фонду, профіль організації та генератор розділів. Аналізатор на базі Claude Sonnet 4.5 перетворює конкурсну документацію в структурований JSON з лімітами, ключовими словами та критеріями оцінки. Профіль організації зберігає попередні заявки, публікації та резюме команди у векторній базі ChromaDB. Генератор для кожного розділу використовує спеціалізований промпт, вбудовуючи релевантні докази з архіву.
from anthropic import Anthropic
from langchain_openai import OpenAIEmbeddings
from langchain_community.vectorstores import Chroma
import json
from pathlib import Path
client = Anthropic()
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
class GrantRequirementsAnalyzer:
"""Аналізує вимоги грантового фонду"""
def parse_call_for_proposals(self, cfp_text: str) -> dict:
"""Витягує структуровані вимоги з конкурсної документації"""
response = client.messages.create(
model="claude-sonnet-4-5",
max_tokens=2048,
messages=[{
"role": "user",
"content": f"""Проаналізуй конкурсну документацію та витягни вимоги.
Поверни JSON:
{{
"funder_name": "назва фонду",
"program_name": "назва програми",
"max_grant_size": "сума або null",
"eligible_organizations": ["тип орг. 1", "тип орг. 2"],
"priority_areas": ["пріоритет 1", "пріоритет 2"],
"required_sections": [
{{"name": "назва розділу", "max_words": 500, "description": "що має бути"}}
],
"evaluation_criteria": [
{{"criterion": "назва", "weight": "відсоток або опис"}}
],
"key_keywords": ["ключові слова для використання"],
"prohibited": ["що не можна вказувати або робити"],
"deadline": "дата або null",
"reporting_requirements": "вимоги до звітності"
}}
Документація:
{cfp_text[:8000]}
Тільки JSON."
}],
)
text = response.content[0].text
return json.loads(text[text.find("{"):text.rfind("}") + 1])
class OrganizationProfileBuilder:
"""Будує профіль організації для повторного використання в заявках"""
def __init__(self, org_id: str):
self.vectorstore = Chroma(
collection_name=f"org_profile_{org_id}",
embedding_function=embeddings,
)
def add_document(self, doc_type: str, content: str, metadata: dict = {}):
"""
doc_type: "previous_grant" | "publication" | "team_bio" |
"project_results" | "financial_report" | "partner_letter"
"""
self.vectorstore.add_texts(
texts=[content],
metadatas=[{"doc_type": doc_type, **metadata}]
)
def find_relevant_evidence(self, query: str, doc_types: list = None) -> list[dict]:
"""Знаходить релевантні матеріали з архіву організації"""
filter_dict = {"doc_type": {"$in": doc_types}} if doc_types else None
results = self.vectorstore.similarity_search_with_score(
query, k=6, filter=filter_dict
)
return [
{
"content": doc.page_content,
"doc_type": doc.metadata.get("doc_type"),
"relevance": round(1 - score, 2),
}
for doc, score in results
if (1 - score) > 0.5
]
class GrantSectionWriter:
"""Пише окремі розділи грантової заявки"""
SECTION_PROMPTS = {
"problem_statement": """Напиши розділ «Обґрунтування проблеми».
Використовуй дані та статистику. Покажи значущість проблеми для цільової аудиторії фонду.
Уникай загальних слів — конкретні факти, посилання на дослідження.""",
"objectives": """Напиши розділ «Цілі та завдання проекту».
Цілі мають бути SMART: конкретними, вимірюваними, досяжними, релевантними, обмеженими в часі.
Формат: 1-2 цілі + 4-6 завдань.""",
"methodology": """Напиши розділ «Методологія / план реалізації».
Детальний опис: етапи, методи, інструменти, строки.
Включи план управління ризиками.""",
"expected_results": """Напиши розділ «Очікувані результати та показники».
Чіткі кількісні KPI. Як буде вимірюватися успіх?
Розділити: прямі результати (outputs), результати змін (outcomes), довгостроковий вплив (impact).""",
"team": """Напиши розділ «Команда проекту».
Компетенції ключових учасників. Релевантний досвід. Чому саме ця команда впорається?""",
"budget_justification": """Напиши обґрунтування бюджету.
Кожна стаття витрат має бути обґрунтована необхідністю для проекту.
Покажи відповідність запитуваних сум ринковим цінам.""",
"sustainability": """Напиши розділ «Стійкість проекту».
Як проект розвиватиметься/підтримуватиметься після закінчення грантового періоду?
Джерела подальшого фінансування.""",
"innovation": """Напиши розділ «Новизна та інноваційність».
У чому унікальність підходу? Чим відрізняється від існуючих рішень?""",
}
def write_section(
self,
section_name: str,
project_brief: dict,
requirements: dict,
org_evidence: list[dict],
word_limit: int = 500,
) -> str:
"""Генерує розділ заявки"""
section_instruction = self.SECTION_PROMPTS.get(
section_name,
f"Напиши розділ '{section_name}'."
)
evidence_text = ""
if org_evidence:
evidence_text = "\n\nРелевантні матеріали організації:\n" + "\n\n".join([
f"[{e['doc_type']}]: {e['content'][:500]}"
for e in org_evidence[:4]
])
keywords_instruction = ""
if requirements.get("key_keywords"):
keywords_instruction = f"\nВажно використовувати ключові слова фонду: {', '.join(requirements['key_keywords'][:10])}"
response = client.messages.create(
model="claude-sonnet-4-5",
max_tokens=2048,
system=f"""Ти — експерт з написання грантових заявок.
Пишеш для фонду: {requirements.get('funder_name', 'невідомий')}.
Програма: {requirements.get('program_name', '')}.
Пріоритети фонду: {', '.join(requirements.get('priority_areas', []))}.
Обмеження: {word_limit} слів.{keywords_instruction}
Стиль: професійний, конкретний, орієнтований на результат.
НЕ використовуй шаблонні фрази на кшталт «даний проект спрямований на...»""",
messages=[{
"role": "user",
"content": f"""{section_instruction}
Опис проекту:
{json.dumps(project_brief, ensure_ascii=False, indent=2)}
{evidence_text}
Напиши розділ ({word_limit} слів)."""
}],
)
return response.content[0].text
class GrantApplicationSystem:
"""Повна система генерації грантових заявок"""
def __init__(self, org_id: str):
self.analyzer = GrantRequirementsAnalyzer()
self.org_profile = OrganizationProfileBuilder(org_id)
self.writer = GrantSectionWriter()
def generate_full_application(
self,
cfp_text: str,
project_brief: dict,
) -> dict:
"""Генерує повну грантову заявку"""
# 1. Аналізуємо вимоги фонду
requirements = self.analyzer.parse_call_for_proposals(cfp_text)
# 2. Генеруємо розділи
application = {
"metadata": {
"funder": requirements.get("funder_name"),
"program": requirements.get("program_name"),
"generated_at": __import__("datetime").datetime.now().isoformat(),
},
"sections": {},
}
for section_req in requirements.get("required_sections", []):
section_name = section_req["name"]
word_limit = section_req.get("max_words", 500)
# Знаходимо релевантні матеріали з архіву
query = f"{section_name} {project_brief.get('title', '')} {project_brief.get('problem', '')}"
evidence = self.org_profile.find_relevant_evidence(
query,
doc_types=["previous_grant", "project_results", "publication"],
)
# Мапінг назв розділів на типи промптів
section_type = self._map_section_type(section_name)
content = self.writer.write_section(
section_name=section_type,
project_brief=project_brief,
requirements=requirements,
org_evidence=evidence,
word_limit=word_limit,
)
application["sections"][section_name] = {
"content": content,
"word_count": len(content.split()),
"word_limit": word_limit,
}
# 3. Перевіряємо відповідність критеріям
application["compliance_check"] = self._check_compliance(
application["sections"],
requirements,
)
return application
def _map_section_type(self, section_name: str) -> str:
"""Мапінг довільних назв розділів на типи"""
name_lower = section_name.lower()
mapping = {
"problem": "problem_statement",
"проблем": "problem_statement",
"цілі": "objectives",
"завдан": "objectives",
"методол": "methodology",
"план": "methodology",
"результат": "expected_results",
"команд": "team",
"бюджет": "budget_justification",
"стійк": "sustainability",
"нов": "innovation",
"інновац": "innovation",
}
for key, value in mapping.items():
if key in name_lower:
return value
return "problem_statement"
def _check_compliance(self, sections: dict, requirements: dict) -> dict:
"""Перевіряє заявку на відповідність вимогам"""
issues = []
warnings = []
# Перевіряємо обсяги
for section_name, section_data in sections.items():
if section_data["word_count"] > section_data["word_limit"] * 1.1:
issues.append(f"Розділ '{section_name}': перевищено ліміт слів ({section_data['word_count']} > {section_data['word_limit']})")
# Перевіряємо наявність ключових слів
all_text = " ".join(s["content"] for s in sections.values()).lower()
for keyword in requirements.get("key_keywords", [])[:5]:
if keyword.lower() not in all_text:
warnings.append(f"Відсутнє ключове слово: '{keyword}'")
return {
"passed": len(issues) == 0,
"issues": issues,
"warnings": warnings,
}
Практичний кейс: наш клієнт — НКО, 12 заявок на рік
Ситуація: некомерційна організація подає 10–15 заявок на рік у різні фонди. Кожна заявка вимагає переробки під вимоги конкретного фонду. 2–3 співробітники витрачали сумарно 600+ годин на рік.
Ось що ми зробили:
- Проіндексували 35 попередніх успішних заявок у профіль організації.
- Система генерує чорнові розділи за 15–20 хвилин.
- Compliance-чекер перевіряє відповідність лімітам та ключовим словам.
- Фінальне редагування живим автором: 6–10 годин замість 40–80.
Результати:
| Показник | До впровадження | Після впровадження |
|---|---|---|
| Час підготовки однієї заявки | 50–80 год | 8–12 год |
| Кількість заявок на рік (та ж команда) | 12 | 22 |
| Відсоток успішних заявок | 46% | 46% |
Важливе обмеження: AI-чернетка потребує ретельної перевірки. У заявках для Сколково система включила формулювання з попередніх заявок, які суперечили новим вимогам програми. Compliance-чекер цього не впіймав — додали крок ручного перегляду критеріїв оцінки перед фінальною подачею.
Чому AI-генерація ефективніша за традиційні шаблони?
Порівняно з ручним написанням або простими шаблонами, наша система дає триразовий виграш: AI-генерація в 5 разів швидша, ніж написання з нуля, і в 2 рази швидша, ніж редагування торішньої заявки під новий фонд. Крім того, compliance-чекер автоматично виявляє невідповідності ключовим словам та лімітам, знижуючи ризик відхилення через формальні помилки. Економія бюджету організації — до 1.5 млн грн на рік при активній роботі з грантами.
В основі лежать великі мовні моделі (LLM) — від Claude до GPT, — які донавчаються (fine-tuning) на ваших успішних заявках для підвищення релевантності. Механізм пошукового доповнення генерації (RAG) витягує з векторної бази (ChromaDB) релевантні фрагменти архіву, а compliance-модуль проводить грантовий аудит кожного розділу на відповідність формальним критеріям.
«Автоматизація чорнової роботи дозволила нашій команді зосередитися на змістовній частині — за рік ми подали на 80% більше заявок при тих же трудозатратах.» — проектний менеджер НКО-клієнта
Як AI-генерація підвищує якість заявок?
Генератор не просто копіює старі заявки — він адаптує наратив під критерії конкретного фонду. Аналізатор виділяє приховані пріоритети, а профіль організації підтягує релевантні докази. Compliance-модуль перевіряє кожен розділ на відповідність лімітам слів та ключовим словам. У результаті заявка виходить більш точною та цілісною, що підвищує шанси на успіх.
Склад робіт з впровадження
- Аналіз конкурсної документації та витягнення прихованих вимог.
- Побудова профілю організації з індексацією архіву (до 1000 документів).
- Генерація чернеток усіх розділів з урахуванням ваших даних та ключових слів фонду.
- Compliance-перевірка на відповідність лімітам слів, ключовим словам та критеріям оцінки.
- Документація з розгортання або надання доступу до веб-інтерфейсу.
- Навчання співробітників (2–3 години) та пост-релізна підтримка 30 днів.
Етапи впровадження
- Аудит поточних процесів — збір заявок, конкурсної документації, визначення типових сценаріїв.
- Індексація архіву — завантаження документів у векторну базу ChromaDB, налаштування ембедингів.
- Налаштування генератора — адаптація промптів під стилістику фондів, за потреби fine-tuning моделі.
- Інтеграція — розгортання на вашій інфраструктурі або надання SaaS-доступу.
- Навчання та приймання — пілотування на одній заявці, передача документації.
Строки
| Етап | Строк |
|---|---|
| Аналізатор вимог фонду | 3–5 днів |
| Профіль організації + індексування архіву | 3–5 днів |
| Генератор розділів + compliance-чекер | 1 тиждень |
| Повна система з веб-інтерфейсом | 3–4 тижні |
Вартість розраховується індивідуально залежно від обсягу архіву, кількості фондів та необхідної інтеграції. Наша компанія — більше 5 років на ринку, 70+ реалізованих проектів в AI/ML. Ми гарантуємо якість кожного етапу: від аналізу до впровадження. Зв'яжіться з нами — оцінимо ваш проект і підготуємо пропозицію. Отримайте консультацію з впровадження AI в грантовий процес.







