v2: Initial clean branch with unit tests + CI/CD pipeline
- Started from ac75faa (initial E4B-MarkBase integration)
- Kept Sources/ (all engine code) + Package.swift + .gitignore
- Removed all ad-hoc tests, documentation, scripts, Python files
- Added Tests/00_Unit/ (MathTest, TokenizerTest, SamplerTest)
- Added .gitea/workflows/ci.yaml (build + unit tests + lint)
- Added Scripts/check_resources.sh (memory-aware test runner)
- Added Tests/Manifest.json (resource requirements for all tests)
- Focus: 4-bit quantized models only
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
import XCTest
|
||||
@testable import MarkBase
|
||||
|
||||
final class SamplerTest: XCTestCase {
|
||||
|
||||
var sampler: Sampler!
|
||||
|
||||
override func setUp() {
|
||||
super.setUp()
|
||||
sampler = Sampler()
|
||||
}
|
||||
|
||||
// MARK: - Top-K Sampling
|
||||
|
||||
func testTopKFilter() {
|
||||
var logits = [Float](repeating: 0, count: 100)
|
||||
logits[10] = 10.0
|
||||
logits[20] = 9.0
|
||||
logits[30] = 8.0
|
||||
|
||||
let result = sampler.sample(logits: logits, temperature: 1.0, topK: 3, topP: 1.0)
|
||||
XCTAssertTrue([10, 20, 30].contains(result),
|
||||
"Should sample from top-3 tokens (\(result))")
|
||||
}
|
||||
|
||||
func testTopKZero() {
|
||||
var logits = [Float](repeating: 0, count: 100)
|
||||
logits[50] = 5.0
|
||||
|
||||
let result = sampler.sample(logits: logits, temperature: 1.0, topK: 0, topP: 1.0)
|
||||
XCTAssertGreaterThanOrEqual(result, 0)
|
||||
XCTAssertLessThan(result, 100)
|
||||
}
|
||||
|
||||
// MARK: - Temperature
|
||||
|
||||
func testTemperatureZeroGreedy() {
|
||||
var logits = [Float](repeating: -10, count: 1000)
|
||||
logits[42] = 20.0
|
||||
|
||||
let result = sampler.sample(logits: logits, temperature: 0.0, topK: 1, topP: 1.0)
|
||||
XCTAssertEqual(result, 42, "Temperature 0 should always select highest logit")
|
||||
}
|
||||
|
||||
func testTemperatureHigh() {
|
||||
var logits = [Float](repeating: 0, count: 1000)
|
||||
logits[0] = 100.0
|
||||
|
||||
let result = sampler.sample(logits: logits, temperature: 10.0, topK: 100, topP: 1.0)
|
||||
XCTAssertEqual(result, 0, "Overwhelming logit should still be selected")
|
||||
}
|
||||
|
||||
// MARK: - Unused Token Filtering
|
||||
|
||||
func testFilterUnusedTokens() {
|
||||
var logits = [Float](repeating: 0, count: 262144)
|
||||
logits[258123] = 30.0
|
||||
logits[500] = 29.0
|
||||
|
||||
let result = sampler.sample(logits: logits, temperature: 1.0, topK: 50, topP: 0.95, filterUnusedTokens: true)
|
||||
XCTAssertLessThan(result, 258000, "Should not sample unused tokens when filtering enabled")
|
||||
}
|
||||
|
||||
func testNoUnusedTokenFilter() {
|
||||
var logits = [Float](repeating: 0, count: 262144)
|
||||
logits[258123] = 50.0
|
||||
logits[500] = 0.0
|
||||
|
||||
let result = sampler.sample(logits: logits, temperature: 1.0, topK: 10, topP: 1.0, filterUnusedTokens: false)
|
||||
XCTAssertEqual(result, 258123, "Should allow unused tokens when filtering disabled")
|
||||
}
|
||||
|
||||
// MARK: - Edge Cases
|
||||
|
||||
func testAllSameLogits() {
|
||||
let logits = [Float](repeating: 1.0, count: 1000)
|
||||
let result = sampler.sample(logits: logits, temperature: 1.0, topK: 100, topP: 1.0)
|
||||
XCTAssertGreaterThanOrEqual(result, 0)
|
||||
XCTAssertLessThan(result, 1000)
|
||||
}
|
||||
|
||||
func testSingleToken() {
|
||||
let logits: [Float] = [5.0]
|
||||
let result = sampler.sample(logits: logits, temperature: 1.0, topK: 1, topP: 1.0)
|
||||
XCTAssertEqual(result, 0)
|
||||
}
|
||||
|
||||
func testExtremeTemperatureZero() {
|
||||
var logits = [Float](repeating: -100, count: 100)
|
||||
logits[7] = 50.0
|
||||
|
||||
// Greedy: temperature=0, topK=1
|
||||
let result = sampler.sample(logits: logits, temperature: 0.0, topK: 1, topP: 1.0)
|
||||
XCTAssertEqual(result, 7)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user