AI Automation of Commercial Proposal Generation
A manager spends 1–3 hours per commercial proposal per client. An AI system generates personalized commercial proposal in 2–5 minutes: extracts data from CRM, selects relevant case studies, formulates value proposition for client's specific pain points, assembles PDF with branded design.
System Architecture
CRM data (AmoCRM/Bitrix24) + industry template
↓ GPT-4o: content and structure personalization
↓ Case study selection from knowledge base (vector search)
↓ PDF generation (WeasyPrint / python-docx)
↓ Open tracking (pixel tracking / DocuSign)
Personalized Proposal Generator
from openai import AsyncOpenAI
from dataclasses import dataclass
import json
client = AsyncOpenAI()
@dataclass
class ProposalBrief:
client_name: str
client_company: str
industry: str
pain_points: list[str] # from manager CRM notes
budget_tier: str # small (<500k), mid (500k-3M), enterprise (3M+)
decision_maker_role: str # CTO, CEO, CMO, Head of IT
service_type: str
relevant_cases: list[dict] # from case database
manager_name: str
deadline_pressure: bool = False
async def generate_commercial_proposal(brief: ProposalBrief) -> dict:
cases_summary = "\n".join([
f"- {c['client']} ({c['industry']}): {c['result']}"
for c in brief.relevant_cases[:3]
])
response = await client.chat.completions.create(
model="gpt-4o",
messages=[{
"role": "system",
"content": f"""You are a B2B copywriter, expert in persuasive commercial proposals.
Create a proposal focused on the decision maker: {brief.decision_maker_role}.
STRUCTURE:
1. Personal greeting (client's pain, not our achievements)
2. Problem understanding (show you understand the challenge)
3. Our solution (concrete to their task, not generic service)
4. Why us (case studies, numbers, not words)
5. What you'll get (measurable result)
6. Next steps (concrete CTA with date)
Tone: confident, no flattery or clichés ("we're pleased to offer...").
Client budget level: {brief.budget_tier} — adjust detail accordingly.
{"Add urgency emphasis to solution." if brief.deadline_pressure else ""}
Return JSON: {{executive_summary, problem_statement, solution_description, why_us, deliverables, next_steps, subject_line}}"""
}, {
"role": "user",
"content": f"""
Client: {brief.client_name}, {brief.client_company} ({brief.industry})
Pain points: {', '.join(brief.pain_points)}
Service: {brief.service_type}
Relevant case studies:
{cases_summary}
Manager: {brief.manager_name}
"""
}],
response_format={"type": "json_object"}
)
return json.loads(response.choices[0].message.content)
Relevant Case Study Search via Vector Database
from openai import OpenAI
import numpy as np
sync_client = OpenAI()
def find_relevant_cases(
client_industry: str,
pain_points: list[str],
case_database: list[dict],
top_k: int = 3
) -> list[dict]:
"""Find cases semantically similar to client's task"""
query = f"{client_industry}: {', '.join(pain_points)}"
query_embedding = sync_client.embeddings.create(
model="text-embedding-3-small",
input=query
).data[0].embedding
scored_cases = []
for case in case_database:
case_text = f"{case['industry']}: {case['challenge']} → {case['result']}"
case_embedding = sync_client.embeddings.create(
model="text-embedding-3-small",
input=case_text
).data[0].embedding
similarity = np.dot(query_embedding, case_embedding) / (
np.linalg.norm(query_embedding) * np.linalg.norm(case_embedding)
)
scored_cases.append((similarity, case))
return [case for _, case in sorted(scored_cases, reverse=True)[:top_k]]
PDF Assembly with Branded Design
from weasyprint import HTML, CSS
from jinja2 import Environment, FileSystemLoader
import base64
def render_proposal_pdf(proposal_data: dict, template_name: str = "default") -> bytes:
env = Environment(loader=FileSystemLoader("templates/proposals"))
template = env.get_template(f"{template_name}.html")
html_content = template.render(**proposal_data)
# Branded CSS with brand color variables
css = CSS(string="""
@page { size: A4; margin: 20mm 15mm; }
body { font-family: 'Inter', sans-serif; color: #1a1a2e; }
.highlight { background: #f0f4ff; border-left: 4px solid #4361ee; padding: 12px; }
.case-block { border: 1px solid #e2e8f0; border-radius: 8px; padding: 16px; }
""")
pdf_bytes = HTML(string=html_content).write_pdf(stylesheets=[css])
return pdf_bytes
CRM Integration
System connects to AmoCRM or Bitrix24 via API: when deal moves to "Proposal Preparation" stage, automatically requests contact data, conversation history from manager notes, service type from deal field. Manager receives draft within 2–3 minutes and makes final edits in web editor before sending.
Tracking implemented via pixel in HTML email or DocuSign API — manager sees when client opened proposal and time spent on each page.
Personalization Variants by Decision Maker Role
| Role | Proposal Focus | Language |
|---|---|---|
| CEO | ROI, strategic impact, risks of inaction | Business results |
| CTO | Architecture, technology, timeline, code quality | Technical |
| CFO | TCO, payback, FTE savings | Financial metrics |
| CMO | Acquisition metrics, conversion, brand awareness | Marketing KPI |
Proposal generator with single CRM integration and PDF export — 2–3 weeks. Full platform with case base, tracking, A/B testing proposal versions, and conversion analytics — 6–8 weeks.







