Skip to content

Self-hosted coding-assistant backend ​

Power an internal Cursor / Continue / Aider deployment with Bigwave, with a feedback loop that fine-tunes a code model on the team's own corpus.

The problem ​

Your engineers want Cursor's productivity. AppSec said no — source code can't leave the perimeter. Your options are:

  • Buy enterprise Cursor. Long procurement, still some data-handling concessions, expensive at scale.
  • Switch everyone to a self-host-friendly tool (Continue.dev, Aider, Tabby). The IDE side works; the back-end stack is bring your own.

The third option is the gap Bigwave fills: be the OpenAI-compatible back-end behind whichever IDE-side tool your team picks, with a feedback loop that turns thumbs / regenerate / reject signals into a DPO-tuned model that knows your team's idioms.

The Bigwave shape ​

ComponentRole
ServingEngine.ollama (or vLLM roadmap)Serves a code-capable model: qwen2.5-coder:7b, deepseek-coder:6.7b, or your own
OpenAI-compatible /v1/chat/completionsWhat Continue.dev / Cursor / Aider talk to
FeedbackStoreCaptures thumbs from the IDE-side tool's feedback widget
CompletionProvenanceCacheResolves completion_id → (model, adapter, workspace) so feedback rows are linkable
dataset_builderTurns thumbs into preference pairs
TrainingBackend.unsloth (DPO recipe)Fine-tunes the code model on the team's preferences
EvalGateRefuses regressed adapters at activation
AuditLogRepositoryTells AppSec what data was used and when

End-to-end walkthrough ​

1. Pick a code-capable model ​

Code models matter more than chat models here. Defaults that work well on consumer hardware:

ModelVRAM (Q4)Strengths
qwen2.5-coder:7b~6 GBPermissive licence, strong on Python/JS/TS, good context window
deepseek-coder:6.7b~5 GBFast, focused on coding, lower-latency completions
codellama:13b~10 GBOlder but well-understood
bash
./install.sh --non-interactive \
    --non-interactive \
    --model=qwen2.5-coder:7b \
    --port=8080

2. Wire Continue.dev ​

Continue.dev is the easiest IDE integration today. Install the extension in VS Code / JetBrains, then point its config.json at Bigwave:

jsonc
// ~/.continue/config.json
{
  "models": [
    {
      "title": "Bigwave (Qwen Coder 7B)",
      "provider": "openai",
      "model": "qwen2.5-coder:7b",
      "apiBase": "http://bigwave.internal:8000/v1",
      "apiKey": "BIGWAVE_BEARER_HERE"
    }
  ],
  "tabAutocompleteModel": {
    "title": "Bigwave Autocomplete",
    "provider": "openai",
    "model": "qwen2.5-coder:7b",
    "apiBase": "http://bigwave.internal:8000/v1",
    "apiKey": "BIGWAVE_BEARER_HERE"
  }
}

That's it. Continue.dev's chat panel, autocomplete, and command palette now route through bigwave. Source code stays on your network.

3. Capture feedback ​

Continue.dev posts an acceptance event when a developer accepts or rejects a completion. Bigwave's feedback endpoint accepts this signal:

python
import requests

# Map Continue.dev's "accepted" / "rejected" to bigwave's rating.
rating = 1 if accepted else -1
requests.post(
    f"http://bigwave.internal:8000/v1/chat/completions/{completion_id}/feedback",
    headers={"Authorization": f"Bearer {bearer}"},
    json={"rating": rating, "label": "completion-accepted" if accepted else "completion-rejected"},
)

Where completion_id comes from the chat completion response's id field (which Bigwave stamps on every response).

A small Continue.dev plugin / userscript bridges acceptance → bigwave-feedback. You can also instrument this in your IDE-side extension if you've forked Continue.

4. Wait for signal ​

The DPO loop wants ~500–2000 preference pairs to produce a measurable delta. With an active engineering team this lands within a couple of weeks. The Loop dashboard at http://bigwave.internal:8080 shows the current rollup.

A useful interim ritual: weekly review of the highest-disagreement buckets (where the model's accepted-rate is lowest) — those are your fine-tune targets.

5. Build the preference dataset ​

bash
curl -H "Authorization: Bearer $BIGWAVE_ADMIN_TOKEN" \
     -H "Content-Type: application/json" \
     "http://bigwave.internal:8000/admin/feedback/build-dataset" \
     -d '{
       "strategy": "thumbs_pair",
       "since": "2026-04-01T00:00:00Z",
       "model": "qwen2.5-coder:7b",
       "min_pairs": 500
     }'
# {"dataset_id": "ds-prefs-...", "n_pairs": 1247, ...}

Or via the Web UI: Feedback dashboard → pick thumbs_pair strategy → Build dataset → Train DPO →. The Training screen prefills with recipe="dpo".

6. Train DPO ​

bash
curl -H "Authorization: Bearer $BIGWAVE_ADMIN_TOKEN" \
     -H "Content-Type: application/json" \
     "http://bigwave.internal:8000/admin/training/jobs" \
     -d '{
       "base_model": "qwen2.5-coder:7b",
       "dataset_id": "ds-prefs-...",
       "recipe": "dpo",
       "hparams": {"lr": 5e-6, "beta": 0.1, "epochs": 1},
       "eval_split": 0.1
     }'

DPO is a single-pass fine-tune with low learning rate; the recipe is conservative by default to avoid clobbering the base model's general capability.

7. Eval against the team's golden set ​

A code-team golden set is best assembled organically: 50–200 representative prompts the team agrees the model should do well on. Examples:

  • "Write a Python decorator that caches a function's result for N seconds." (style + correctness)
  • "Add error handling to this fetch wrapper." (code-context understanding)
  • "Refactor this React component to use the new hooks API." (idiom matching)

Score the candidate:

bash
# Submit eval run against the candidate
curl -H "Authorization: Bearer $BIGWAVE_ADMIN_TOKEN" \
     -H "Content-Type: application/json" \
     "http://bigwave.internal:8000/admin/evals/runs" \
     -d @./team-golden-eval.json

For code, exact-match is usually too strict. Wire an LLM-as-judge scorer or compile/test-pass scorers (these are adjacent capabilities).

8. Activate ​

bash
curl -H "Authorization: Bearer $BIGWAVE_ADMIN_TOKEN" \
     "http://bigwave.internal:8000/admin/models/qwen2.5-coder:7b/adapters" \
     -d '{"adapter_id": "adp-dpo-..."}'

The drain-and-swap activation drops zero in-flight requests. Anyone using Continue.dev right now sees their next completion come from the new adapter; their current request finishes against the old one.

9. Verify the delta ​

The Loop dashboard shows the active adapter and the latest eval pass-rate. Drive a few representative prompts through both the base and the DPO'd adapter:

python
def chat(adapter_id, prompt):
    return openai.OpenAI(...).chat.completions.create(
        model="qwen2.5-coder:7b",
        messages=[{"role": "user", "content": prompt}],
        extra_body={"bigwave_adapter_id": adapter_id},
    ).choices[0].message.content

baseline = chat(None, "Write a context manager for a database transaction.")
tuned    = chat("adp-dpo-...", "Write a context manager for a database transaction.")

For a fair before/after, run both against your golden set and compare pass-rates. Document the delta.

What you'll have at the end ​

  • A self-hosted code-completion back-end your engineers actually use, that AppSec signed off on.
  • A DPO'd adapter measurably better than the base on your team's prompts.
  • A continuous feedback loop where every accept/reject from the IDE becomes future training signal.
  • An audit log of every dataset, training job, and adapter activation — useful when AppSec asks "what data did you train on."

What's not covered here ​

  • Tabby integration. The Tabby completion server has a different API; Bigwave's OpenAI-compat surface fits Continue.dev / Aider / Cursor better. Tabby integration is on the roadmap roadmap.
  • Embedding inline-completion latency below ~100ms. Cursor's edge is sub-100ms first-token; on a single-GPU Bigwave host you should expect 200–500ms. Acceptable for chat panel, not for every-keystroke autocomplete on a large codebase.
  • Multi-tenant per-team adapters. The workspace fence supports this, but you need a routing layer in front of Bigwave to direct team-A's IDE traffic to adapter-A and team-B's to adapter-B.
  • Code-quality eval scorers. Compile-rate / test-pass-rate scorers are roadmap; for now you'll be using LLM-as-judge or exact-match.

AppSec talking points ​

You'll be asked. The honest answers:

QuestionAnswer
Does any code leave our network?No. The ServingEngine.ollama adapter speaks to a local Ollama; the gateway makes no outbound paid-API call. Verify with curl --max-time 5 https://api.openai.com/ from inside the API container — it should fail.
What about model downloads?Ollama pulls the base model once at install time from https://registry.ollama.ai/. After that, no outbound. You can mirror this internally and remove egress entirely.
Where is fine-tuned data stored?In the configured BIGWAVE_DATA_DIR on the GPU host. WorkspaceFence keeps team-A's data invisible to team-B.
What about supply-chain?License-check CI runs on every commit; GPL/AGPL are blocked from the runtime path.

See also ​

Dual-licensed: MIT OR Apache-2.0