187 lines
5.2 KiB
Markdown
187 lines
5.2 KiB
Markdown
# Swiftblade — Swift Specialist LoRA
|
||
|
||
Adapter codename: `swiftblade`
|
||
Agent: `build-swift`
|
||
Base model: Qwen/Qwen3.5-27B
|
||
|
||
## Objective
|
||
|
||
Teach the model Swift/Apple-idiomatic code generation aligned with the build-swift
|
||
agent's system prompt. The adapter should internalize:
|
||
|
||
- Swift 6 strict concurrency (`@Sendable`, `sending`, `@MainActor`)
|
||
- SwiftUI first, UIKit only when necessary
|
||
- `guard` for early exits, proper optional binding
|
||
- Value types over reference types where appropriate
|
||
- `URLSession` for networking (no Alamofire)
|
||
- swift build → swift test verification cycle
|
||
- Architecture detection (MVVM, TCA, MV)
|
||
|
||
## Current Status
|
||
|
||
build-swift currently runs on `anthropic/claude-sonnet-4-6` as a quality backstop.
|
||
The swiftblade adapter is intended as a local replacement, but deployment depends
|
||
on evaluation results. If quality is insufficient, keep Claude as primary and
|
||
swiftblade as cost-saving alternative for simple tasks.
|
||
|
||
## Data Sources
|
||
|
||
### Session extraction (~20–40 examples)
|
||
|
||
Swift sessions are rare. Classify by:
|
||
- File paths: `.swift`, `Package.swift`, `*.xcodeproj`, `project.yml`
|
||
- Bash commands: `swift build`, `swift test`, `xcodebuild`, `swift-format`
|
||
- Error patterns: swiftc diagnostics, `error:`, `cannot convert`, `protocol conformance`
|
||
|
||
### Git repo mining (~30–60 examples)
|
||
|
||
Target repos:
|
||
- `madcat-os/madcat-apple` — iOS/macOS app
|
||
- Any Swift packages in madcat-os org
|
||
|
||
Extract patterns:
|
||
- SwiftUI view implementations
|
||
- `@Observable` / `ObservableObject` view model patterns
|
||
- async/await networking with `URLSession`
|
||
- Swift Package Manager configuration
|
||
- Actor-based state isolation
|
||
|
||
### Synthetic (~80–150 examples)
|
||
|
||
Swift is the most synthetic-heavy adapter:
|
||
- Swift 6 concurrency: actors, `@Sendable`, `TaskGroup`, structured concurrency
|
||
- SwiftUI: `@State`, `@Binding`, `@Environment`, custom modifiers
|
||
- Navigation: `NavigationStack`, `NavigationSplitView`, navigation paths
|
||
- Data flow: `@Observable` macro (Swift 5.9+), `@Bindable`
|
||
- Platform-specific: `#available`, multi-platform targets
|
||
- Swift Testing framework (`@Test`, `#expect`, `@Suite`) vs XCTest
|
||
- Combine → async/await migration patterns
|
||
- Widget/extension development
|
||
|
||
## Example Format
|
||
|
||
```json
|
||
{
|
||
"messages": [
|
||
{
|
||
"role": "system",
|
||
"content": "<build-swift agent system prompt>"
|
||
},
|
||
{
|
||
"role": "user",
|
||
"content": "Add a settings view with toggle for dark mode and notification preferences"
|
||
},
|
||
{
|
||
"role": "assistant",
|
||
"content": null,
|
||
"tool_calls": [
|
||
{
|
||
"type": "function",
|
||
"function": {
|
||
"name": "glob",
|
||
"arguments": {"pattern": "Sources/**/*.swift"}
|
||
}
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"role": "tool",
|
||
"content": "<file list showing existing views>"
|
||
},
|
||
{
|
||
"role": "assistant",
|
||
"content": null,
|
||
"tool_calls": [
|
||
{
|
||
"type": "function",
|
||
"function": {
|
||
"name": "read",
|
||
"arguments": {"filePath": "Sources/Views/ContentView.swift"}
|
||
}
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"role": "tool",
|
||
"content": "<existing SwiftUI view pattern>"
|
||
},
|
||
{
|
||
"role": "assistant",
|
||
"content": null,
|
||
"tool_calls": [
|
||
{
|
||
"type": "function",
|
||
"function": {
|
||
"name": "write",
|
||
"arguments": {
|
||
"filePath": "Sources/Views/SettingsView.swift",
|
||
"content": "import SwiftUI\n\nstruct SettingsView: View {\n @AppStorage(\"darkMode\") private var darkMode = false\n ..."
|
||
}
|
||
}
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"role": "tool",
|
||
"content": "File written"
|
||
},
|
||
{
|
||
"role": "assistant",
|
||
"content": null,
|
||
"tool_calls": [
|
||
{
|
||
"type": "function",
|
||
"function": {
|
||
"name": "bash",
|
||
"arguments": {"command": "swift build 2>&1"}
|
||
}
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"role": "tool",
|
||
"content": "Build complete!"
|
||
},
|
||
{
|
||
"role": "assistant",
|
||
"content": "SettingsView created. Uses `@AppStorage` for persistence, `Toggle` for dark mode and notifications. Follows existing MVVM pattern. Builds clean."
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
## Evaluation Criteria
|
||
|
||
1. `swift build` passes with no warnings
|
||
2. Swift 6 concurrency: correct `@Sendable`, actor isolation
|
||
3. SwiftUI-first (no UIKit unless justified)
|
||
4. Proper optional handling (`guard let`, `if let`, no force-unwrap)
|
||
5. Value types where appropriate
|
||
6. Architecture matches project (MVVM/TCA/MV detection)
|
||
7. Tool call sequence: explore → read patterns → implement → build → test
|
||
|
||
## Training Config Overrides
|
||
|
||
```python
|
||
MAX_SEQ = 8192
|
||
LR = 5e-5
|
||
```
|
||
|
||
## Estimated Size
|
||
|
||
- 100–200 examples (mostly synthetic)
|
||
- ~0.8M tokens
|
||
- Training time: ~1 hr on H100
|
||
- Adapter size: ~305 MB
|
||
|
||
## Risk: Quality Gap vs Claude
|
||
|
||
Claude Sonnet excels at Swift due to Apple's partnership data. Swiftblade on
|
||
Qwen3.5-27B may underperform on:
|
||
- Complex generics and associated types
|
||
- Protocol-oriented design patterns
|
||
- Platform-specific API knowledge (Core Data, CloudKit, etc.)
|
||
|
||
Mitigation: keep Claude as fallback, use swiftblade for simpler tasks (UI,
|
||
boilerplate, tests). Evaluate before full switchover.
|