跳到正文
DEV Community· Tejas Rawool·· 4 小時前AI 評分41

FreelanceCanvas:Gemma 在本機撰寫客戶提案,從需求簡介到投標盡在一個畫布

FreelanceCanvas: Gemma Writes My Client Proposals Locally, From Brief to Bid in One Canvas

AI 導讀

FreelanceCanvas 透過 Ollama 在本機執行 Gemma(預設模型為 gemma3:1b),根據客戶簡介或 PDF 配對過往項目,並撰寫自由工作者提案。工具亦會整理客戶資料及生成音訊稿;里程碑、價格和風險則由固定三階段範本提供。本機執行令提案文字留在用戶電腦,而項目配對目前使用雜湊向量,並非真正的嵌入向量。

正文

This is a submission for the Hacktoberfest Open-Source AI Challenge Week 2: Side Hustle.

What I Built

Freelancing has a tax nobody invoices. Before a client pays you a rupee, you read their brief twice, google the company, dig through your old projects for something that fits, guess at the scope, and then write the proposal. That can eat a whole evening. Sometimes you lose the bid anyway.

FreelanceCanvas is my attempt to shrink that evening. You paste a client brief (or drop in a PDF) and it gives you back:

  • a quick snapshot of the client
  • the past projects of yours that fit the job best
  • a full proposal written by Gemma, running on my own machine
  • a three-milestone schedule with a price estimate
  • a short risk list
  • an audio script you can listen to later

Code

FreelanceCanvas 🎨💼

Visual Collaborative AI Workstation for Solo Developers, Consultants & Freelancers
"Brainstorm visually. Research faster. Close clients while you touch grass."


🌟 Overview

FreelanceCanvas is an interactive, visual-first whiteboard and autonomous AI workspace tailored for freelancers, solo developers, and technical consultants. Combining playful neo-brutalist collaborative canvas boards with local vector RAG and AI synthesis, it automates the most time-consuming, unbillable freelance chores:

  1. Visual Brainstorming & Whiteboarding: Interactive draggable sticky notes, phase workflows, and real-time team collaboration canvas.
  2. RFP & Brief Ingestion: Drops in client PDFs, Upwork project descriptions, or discovery call transcripts.
  3. Client Reconnaissance: Autonomous background search (SerpApi) on the client's company, tech stack, and market footprint.
  4. Portfolio & Skills Matching: Local vector RAG (Qdrant) searching your personal past projects, case studies, and rate cards.
  5. Scope & Proposal Synthesis: Local LLM reasoning (Gemma via Ollama) generating a complete proposal, Work Breakdown Structure (WBS), milestone…

To run it:

cp .env.example .env
pip install -r requirements.txt
cd frontend && npm install && cd ..
python scripts/seed_profile.py
python scripts/run_all.py

Then open http://localhost:5173. You also need Ollama running with a Gemma model pulled.

How I Built It

The flow is simple enough to draw in text:

brief or PDF -> client lookup -> portfolio search -> Gemma -> proposal, milestones, risks -> audio script
Part What I used
Frontend React, TypeScript, Vite
Backend FastAPI, async SQLAlchemy, SQLite
Model Gemma (gemma3:1b by default) through Ollama
Portfolio search Qdrant in local mode
Client lookup SerpApi (optional)
Audio ElevenLabs (optional)

When you submit a brief, FastAPI saves it and hands the real work to a background task, so the UI never freezes while the model thinks. That task looks up the client, searches my portfolio for similar past work, stitches everything into one prompt, and sends it to Ollama. The call itself is tiny:

payload = {
    "model": settings.OLLAMA_MODEL,
    "prompt": prompt,
    "system": system,
    "stream": False,
}
resp = await client.post(f"{settings.OLLAMA_BASE_URL}/api/generate", json=payload)

Because the prompt includes the matched case studies, the proposal talks about work I have actually done instead of producing the usual "we are a passionate team" filler.

One thing I care about: the app should never die because a key is missing. No SerpApi key? You get a basic client profile. No ElevenLabs key? You get the audio script as a text file. Ollama down or too slow? You get a structured proposal template instead of an error screen. It's not glamorous, but it means the whole loop runs on a laptop with no internet.

What Isn't Finished

I'd rather say this up front than have you find it in the code.

  • Portfolio matching uses lightweight hashed vectors right now, not real embeddings. Swapping in nomic-embed-text through Ollama is the next thing I want to do.
  • Milestones, prices and risks come from a fixed three-phase template. I don't trust a 1B model with numbers yet, so Gemma writes the proposal text and the template handles the money.
  • Login is local only. There are no real multi-user accounts.
  • Canvas notes live in the browser and disappear on refresh.

Why Open Models Matter Here

Client briefs are often under NDA. Sending one to a hosted API feels wrong to me, and running Gemma locally means the proposal text never leaves my machine.

Cost matters too. A freelancer sends a lot of bids and wins a few. If every bid costs API money, the lost ones sting. With a local model, a lost bid costs electricity.

And it's swappable. Changing OLLAMA_MODEL in the .env file gives you a different model without touching any code. A bigger Gemma, or something else, is one line away.

Who Would Pay

Solo developers, consultants and tiny agencies who write proposals every week. I plan to turn this into a subscription product at [PRICE] a month, with the local model as the private default.

What I Learned

Small models write decent prose and unreliable numbers. I spent more time deciding what the model should not do than what it should. Letting it write the narrative while a template owns the pricing made the output far more consistent. The next step is asking Gemma for milestones as JSON and validating it before anything reaches the screen.

Prize Categories

Gemma: the proposal engine runs on gemma3:1b through Ollama, and the demo shows it at [TIMESTAMP].


If you freelance, I'm curious which part of a proposal eats your time: the research, the scoping, or the writing? Tell me in the comments. Issues and PRs are welcome on GitHub.

來源:DEV Community · dev.to