### Setup MLX Python Environment for Ground Truth Source: https://context7.com/yejingyang8963-byte/swift-gemma4-core/llms.txt Set up a Python virtual environment and install mlx-lm for reproducing Python ground truth and verifying token-level parity. ```bash python3 -m venv ~/.mlx-venv && source ~/.mlx-venv/bin/activate pip install mlx-lm python scripts/python_baseline.py ``` -------------------------------- ### Set up Python environment for mlx-lm Source: https://github.com/yejingyang8963-byte/swift-gemma4-core/blob/main/docs/reproducibility.md Creates a virtual environment and installs the mlx-lm package, which includes Apple's MLX runtime and HuggingFace tokenizers bindings. This is the baseline for comparison. ```bash python3 -m venv ~/.mlx-venv source ~/.mlx-venv/bin/activate pip install --upgrade pip pip install mlx-lm ``` -------------------------------- ### Set up Python Environment for Baseline Test Source: https://github.com/yejingyang8963-byte/swift-gemma4-core/blob/main/README.md Create a Python virtual environment and install the mlx-lm package to run the baseline script for verifying chat-template bypass token IDs. ```bash python3 -m venv ~/.mlx-venv source ~/.mlx-venv/bin/activate pip install mlx-lm python scripts/python_baseline.py ``` -------------------------------- ### Verify Token-Level Parity (Python Script) Source: https://github.com/yejingyang8963-byte/swift-gemma4-core/blob/main/comparison/README.md This script verifies byte-exact token-level chat-template parity with Python. It downloads approximately 10 MB for the tokenizer. Ensure you have the mlx-lm package installed in your virtual environment. ```bash python3 -m venv ~/.mlx-venv && source ~/.mlx-venv/bin/activate ``` ```bash pip install mlx-lm ``` ```python python3 scripts/python_baseline.py ``` -------------------------------- ### Create a Feature Branch Source: https://github.com/yejingyang8963-byte/swift-gemma4-core/blob/main/CONTRIBUTING.md Command to create a new topic branch for development, following the convention of starting with 'fix/' or 'feat/'. ```bash git checkout -b fix/some-bug ``` -------------------------------- ### Get current Git commit SHA Source: https://github.com/yejingyang8963-byte/swift-gemma4-core/blob/main/docs/reproducibility.md Retrieves the SHA of the current Git commit. This is used to pin the verification to a specific reproducible state. ```bash git rev-parse HEAD ``` -------------------------------- ### Build Gemma4SwiftCore Project Source: https://github.com/yejingyang8963-byte/swift-gemma4-core/blob/main/examples/BasicGeneration/README.md Builds the Gemma4SwiftCore project in release mode. This command assumes you are in the `examples/BasicGeneration` directory and uses a relative path for the package reference, allowing immediate pickup of local library changes. ```bash cd examples/BasicGeneration swift build -c release ``` -------------------------------- ### Build and Test Gemma4SwiftCore Source: https://github.com/yejingyang8963-byte/swift-gemma4-core/blob/main/CONTRIBUTING.md Commands to clone the repository, build the project, and run specific test suites. ```bash git clone https://github.com/yejingyang8963-byte/Swift-gemma4-core.git cd Swift-gemma4-core swift build swift test --filter "ConfigurationTests|SanitizeTests|ProportionalRoPETests|PromptFormattingTests" ``` -------------------------------- ### Run Automated Pre-push Check Source: https://github.com/yejingyang8963-byte/swift-gemma4-core/blob/main/PUSH_CHECKLIST.md Execute the automated script to verify release readiness. This should be run before the manual checklist. ```bash bash scripts/verify_release.sh ``` -------------------------------- ### Run Full Test Suite with Xcode Source: https://github.com/yejingyang8963-byte/swift-gemma4-core/blob/main/CONTRIBUTING.md Command to execute the complete test suite, including MLX-dependent tests, using Xcode 15.4+ on Apple Silicon. ```bash xcodebuild test -scheme Gemma4SwiftCore -destination 'platform=macOS,arch=arm64' ``` -------------------------------- ### Perform Final Visual Scan Source: https://github.com/yejingyang8963-byte/swift-gemma4-core/blob/main/PUSH_CHECKLIST.md Visually inspect the project directory in Finder. Check for an appropriate file count and ensure no unexpected files like '.DS_Store' are present. ```bash ls -a ``` -------------------------------- ### Run Benchmark with Custom Max Tokens Source: https://github.com/yejingyang8963-byte/swift-gemma4-core/blob/main/comparison/benchmarks.md Execute the Gemma4Verify tool with a specified maximum number of tokens. Ensure you use the release build for accurate performance measurements, as debug builds are significantly slower. ```bash GEMMA4_VERIFY_MAX_TOKENS=64 swift run -c release Gemma4Verify \ "Tell me a short story about a curious fox." ``` -------------------------------- ### Run Gemma4SwiftCore with a Prompt Source: https://github.com/yejingyang8963-byte/swift-gemma4-core/blob/main/examples/BasicGeneration/README.md Executes the Gemma4SwiftCore generator with a specific command-line prompt. The first run will download model weights, which may take a few minutes. Subsequent runs are faster. ```bash swift run -c release gemma4-generate "Tell me a short story about a fox." ``` -------------------------------- ### Load and Stream Gemma4 Model in Swift Source: https://github.com/yejingyang8963-byte/swift-gemma4-core/blob/main/README.md Demonstrates how to register the sidecar handler, load Gemma4 weights, format a prompt using the chat-template bypass, and stream tokens from the model. Ensure necessary imports are included. ```swift import Gemma4SwiftCore import MLX import MLXLLM import MLXLMCommon // 1. Register the sidecar handler with mlx-swift-lm. Idempotent. await Gemma4Registration.registerIfNeeded().value // 2. Load the real 4-bit weights from HuggingFace. // The model is ~1.5 GB and is cached after the first download. let container = try await LLMModelFactory.shared.loadContainer( configuration: ModelConfiguration(id: Gemma4SwiftCore.verifiedModelId)) // 3. Format your prompt using the chat-template bypass. DO NOT use // tokenizer.applyChatTemplate — it is broken on Gemma 4. let prompt = Gemma4PromptFormatter.userTurn("Tell me a short story about a curious fox.") let tokens = await container.encode(prompt) let input = LMInput(tokens: MLXArray(tokens)) // 4. Stream tokens. let stream = try await container.generate( input: input, parameters: GenerateParameters(maxTokens: 200, temperature: 0.8, topP: 0.95)) for await event in stream { if case .chunk(let text) = event { print(text, terminator: "") } } ``` -------------------------------- ### Run Network Integration Tests Source: https://github.com/yejingyang8963-byte/swift-gemma4-core/blob/main/CONTRIBUTING.md Command to run opt-in network integration tests by setting the GEMMA4_TEST_NETWORK environment variable. ```bash GEMMA4_TEST_NETWORK=1 swift test --filter NetworkIntegrationTests ``` -------------------------------- ### Verify LICENSE File Header Source: https://github.com/yejingyang8963-byte/swift-gemma4-core/blob/main/PUSH_CHECKLIST.md Check the first three lines of the LICENSE file to ensure the copyright information is correct. It should reflect the current year and author. ```bash head -3 LICENSE ``` -------------------------------- ### Run Swift Unit Tests Source: https://github.com/yejingyang8963-byte/swift-gemma4-core/blob/main/README.md Execute pure-Swift unit tests for Configuration, Sanitize, ProportionalRoPE math, and PromptFormatter literals. These tests can run anywhere Swift runs. ```bash swift test --filter "ConfigurationTests|SanitizeTests|ProportionalRoPETests|PromptFormattingTests" ``` -------------------------------- ### Search for Project Name Source: https://github.com/yejingyang8963-byte/swift-gemma4-core/blob/main/PUSH_CHECKLIST.md Perform a case-insensitive recursive search for the project name ('Baku' and 'baku') within the working directory. No results should be found. ```bash grep -ri "Baku" Sources Tests docs examples Benchmarks scripts grep -ri "baku" Sources Tests docs examples Benchmarks scripts ``` -------------------------------- ### Run Python baseline script Source: https://github.com/yejingyang8963-byte/swift-gemma4-core/blob/main/docs/reproducibility.md Executes the Python script that loads the Gemma tokenizer, formats a test prompt using apply_chat_template, and prints the resulting token IDs. This establishes the ground truth for token sequences. ```bash cd Swift-gemma4-core python scripts/python_baseline.py ``` -------------------------------- ### Verify Upstream Gap (Shell Script) Source: https://github.com/yejingyang8963-byte/swift-gemma4-core/blob/main/comparison/README.md This script verifies the absence of Gemma 4 models in the adrgrondin/mlx-swift-lm registry. It clones the fork, greps the registry source, and prints the difference. No model download is required. ```bash bash comparison/upstream_attempt.sh ``` -------------------------------- ### Run CPU Benchmarks Source: https://github.com/yejingyang8963-byte/swift-gemma4-core/blob/main/docs/benchmarks.md Execute pure-CPU benchmarks to test library components not requiring MLX or model weights. This is useful for detecting regressions in CPU-bound code paths. ```bash cd Benchmarks swift run -c release benchmarks ``` -------------------------------- ### Convert Video to GIF with ffmpeg Source: https://github.com/yejingyang8963-byte/swift-gemma4-core/blob/main/docs/images/README.md Use this command to convert a recorded video file (e.g., demo.mov) into a GIF format suitable for embedding in README files. Adjust FPS and scale as needed. ```bash ffmpeg -i demo.mov -vf "fps=15,scale=480:-1" -loop 0 demo.gif ``` -------------------------------- ### Format User Prompt with Gemma4PromptFormatter Source: https://context7.com/yejingyang8963-byte/swift-gemma4-core/llms.txt Format a single user message into Gemma 4's '<|turn>' chat protocol. This is recommended for production text generation. Do not use tokenizer.applyChatTemplate due to a swift-jinja rendering bug. ```swift import Gemma4SwiftCore import MLX import MLXLMCommon // Format a plain user prompt. let formatted = Gemma4PromptFormatter.userTurn("Tell me a short story about a curious fox.") // Produces: // <|turn>user // Tell me a short story about a curious fox. // <|turn>model // // Encode with the model's tokenizer — special tokens are correctly resolved. let tokens = await container.encode(formatted) let input = LMInput(tokens: MLXArray(tokens)) // Stream the response. let stream = try await container.generate( input: input, parameters: GenerateParameters(maxTokens: 200, temperature: 0.8, topP: 0.95)) for await event in stream { if case .chunk(let text) = event { print(text, terminator: "") } } ``` -------------------------------- ### Run Swift equivalent test Source: https://github.com/yejingyang8963-byte/swift-gemma4-core/blob/main/docs/reproducibility.md Executes Swift tests to verify that Gemma4PromptFormatter produces the same string as the Python baseline. It also includes an optional network test for byte-for-byte token ID comparison. ```bash swift test --filter PromptFormattingTests ``` ```bash GEMMA4_TEST_NETWORK=1 swift test --filter NetworkIntegrationTests ``` -------------------------------- ### End-to-End Gemma 4 Inference in Swift Source: https://context7.com/yejingyang8963-byte/swift-gemma4-core/llms.txt This Swift code demonstrates the complete process of using Gemma4SwiftCore for text generation. It includes registering the model, loading it, formatting a user prompt, and streaming the generated response. Ensure necessary frameworks like Gemma4SwiftCore, MLX, and MLXLLM are imported. ```swift import Foundation import Gemma4SwiftCore import MLX import MLXLLM import MLXLMCommon @main struct Gemma4App { static func main() async { do { try await run(prompt: "Write a haiku about the ocean at night.") } catch { fputs("❌ error: \(error)\n", stderr) exit(1) } } static func run(prompt: String) async throws { print("Gemma4SwiftCore v\(Gemma4SwiftCore.version)") // 1. Register sidecar — idempotent, safe to call multiple times. await Gemma4Registration.registerIfNeeded().value // 2. Load model (downloads ~1.5 GB on first run, ~6 s warm). let loadStart = Date() let container = try await LLMModelFactory.shared.loadContainer( configuration: ModelConfiguration(id: Gemma4SwiftCore.verifiedModelId)) print(String(format: "Loaded in %.1fs", Date().timeIntervalSince(loadStart))) // 3. Format prompt — NEVER use tokenizer.applyChatTemplate on Gemma 4. let formatted = Gemma4PromptFormatter.userTurn(prompt) let tokens = await container.encode(formatted) print("Prompt tokens: \(tokens.count)") let input = LMInput(tokens: MLXArray(tokens)) // 4. Stream generation. print("\n--- Response ---") let genStart = Date() var firstChunk: TimeInterval? = nil let stream = try await container.generate( input: input, parameters: GenerateParameters(maxTokens: 200, temperature: 0.8, topP: 0.95)) for await event in stream { switch event { case .chunk(let text): if firstChunk == nil { firstChunk = Date().timeIntervalSince(genStart) } print(text, terminator: "") fflush(stdout) case .info(let info): print(String(format: "\n\n[%.2f tok/s | first chunk: %.2fs]", info.tokensPerSecond, firstChunk ?? 0)) case .toolCall: break } } } } ``` -------------------------------- ### Run Gemma4SwiftCore with Default Prompt Source: https://github.com/yejingyang8963-byte/swift-gemma4-core/blob/main/examples/BasicGeneration/README.md Executes the Gemma4SwiftCore generator without a specific prompt, using a neutral default prompt instead. This is useful for quick tests or when no specific input is required. ```bash swift run -c release gemma4-generate ``` -------------------------------- ### Correct Tokenization using Gemma4PromptFormatter Source: https://github.com/yejingyang8963-byte/swift-gemma4-core/blob/main/Sources/Gemma4SwiftCore/Documentation.docc/ChatTemplateBypass.md This code shows the correct method for tokenizing Gemma 4 inputs by using `Gemma4PromptFormatter` to build the prompt string and then encoding it with `tokenizer.encode(text:)`. This bypasses the buggy `applyChatTemplate`. ```swift // ✅ Correct path. let prompt = Gemma4PromptFormatter.userTurn("Hello, what is your name?") let tokens = await container.encode(prompt) let input = LMInput(tokens: MLXArray(tokens)) ``` -------------------------------- ### List All Tracked Files Source: https://github.com/yejingyang8963-byte/swift-gemma4-core/blob/main/PUSH_CHECKLIST.md Display a sorted list of all files currently tracked by Git. Review this list to ensure no sensitive or unnecessary files are included. ```bash git ls-files | sort ``` -------------------------------- ### Tag and Push Release Version Source: https://github.com/yejingyang8963-byte/swift-gemma4-core/blob/main/PUSH_CHECKLIST.md Create an annotated tag for the release version and push it to the remote repository. This action triggers the Release workflow. ```bash git tag -a v0.1.0 -m "v0.1.0 — initial release" git push origin v0.1.0 ``` -------------------------------- ### Run Swift End-to-End Smoke Test (Shell Command) Source: https://github.com/yejingyang8963-byte/swift-gemma4-core/blob/main/comparison/README.md Optional, slow test to run the Swift end-to-end smoke test. This command executes the Gemma4Verify tool with a sample prompt. ```bash swift run Gemma4Verify "Hello, what is your name?" ``` -------------------------------- ### Gemma4PromptFormatter.userTurnWithThinking(_:includeThinking:) Source: https://context7.com/yejingyang8963-byte/swift-gemma4-core/llms.txt Formats a user prompt with an empty system turn that injects the `<|think|>` token, triggering Gemma 4's chain-of-thought mode. The model will prepend a `<|channel>thought ... ` block before the final answer. Strip this block in the UI if raw reasoning is not desired. ```APIDOC ## Gemma4PromptFormatter.userTurnWithThinking(_:includeThinking:) ### Description Formats a user prompt with an empty system turn that injects the `<|think|>` token, triggering Gemma 4's chain-of-thought mode. The model will prepend a `<|channel>thought ... ` block before the final answer. Strip this block in the UI if raw reasoning is not desired. ### Parameters - **prompt** (String) - The user's input prompt. - **includeThinking** (Bool) - Whether to include the thinking token for chain-of-thought. ### Usage Example ```swift import Gemma4SwiftCore // Enable chain-of-thought reasoning (default behavior). let prompt = Gemma4PromptFormatter.userTurnWithThinking( "What is the square root of 144?", includeThinking: true) // Disable thinking explicitly (equivalent to userTurn). let noThinkPrompt = Gemma4PromptFormatter.userTurnWithThinking( "What is the square root of 144?", includeThinking: false) ``` ### Output Example ``` <|turn>system <|think|> <|turn>user What is the square root of 144? <|turn>model ``` ``` -------------------------------- ### Gemma4TextModel Standard Usage and Generation Source: https://context7.com/yejingyang8963-byte/swift-gemma4-core/llms.txt Register the model using Gemma4Registration and load it via LLMModelFactory for standard usage. Inspect KV cache types after construction. For end-to-end generation, use the generate method with appropriate GenerateParameters. ```swift import Gemma4SwiftCore import MLX import MLXLLM import MLXLMCommon // Standard usage — go through LLMModelFactory (recommended). await Gemma4Registration.registerIfNeeded().value let container = try await LLMModelFactory.shared.loadContainer( configuration: ModelConfiguration(id: Gemma4SwiftCore.verifiedModelId)) // Inspect cache types after model construction: // (Access the model directly if needed for advanced use.) let configData = try Data(contentsOf: /* path to config.json */ URL(fileURLWithPath: "")) let config = try JSONDecoder().decode(Gemma4TextConfiguration.self, from: configData) let model = Gemma4TextModel(config) let caches = model.newCache(parameters: nil) // caches[0] is RotatingKVCache (sliding layer, window=1024) // caches[4] is StandardKVCache (full-attention layer, step=1024) // Full end-to-end generation with GenerateParameters: let prompt = Gemma4PromptFormatter.userTurn("Explain quantum entanglement simply.") let tokens = await container.encode(prompt) let input = LMInput(tokens: MLXArray(tokens)) var tokenCount = 0 let stream = try await container.generate( input: input, parameters: GenerateParameters(maxTokens: 300, temperature: 0.7, topP: 0.9)) for await event in stream { switch event { case .chunk(let text): print(text, terminator: "") tokenCount += 1 case .info(let info): print("\n[\(info.promptTokenCount) prompt tokens, \(String(format: "%.1f", info.tokensPerSecond)) tok/s]") case .toolCall: break } } ``` -------------------------------- ### Push to Main Branch Source: https://github.com/yejingyang8963-byte/swift-gemma4-core/blob/main/PUSH_CHECKLIST.md Execute the push command to upload local changes to the main branch of the remote repository. Use the '-u' flag for the initial push to set upstream tracking. ```bash git push -u origin main ``` -------------------------------- ### Load and Run Gemma 4 Model Source: https://github.com/yejingyang8963-byte/swift-gemma4-core/blob/main/Sources/Gemma4SwiftCore/Documentation.docc/Gemma4SwiftCore.md This snippet demonstrates how to register the Gemma 4 sidecar handler, load model weights from HuggingFace, format a prompt using the chat-template bypass, and generate text. Ensure mlx-swift-lm is set up and the model ID is verified. ```swift import Gemma4SwiftCore import MLXLMCommon import MLXLLM // 1. Register the sidecar handler with mlx-swift-lm. await Gemma4Registration.registerIfNeeded().value // 2. Load the real 4-bit weights from HuggingFace. let container = try await LLMModelFactory.shared.loadContainer( configuration: ModelConfiguration(id: Gemma4SwiftCore.verifiedModelId)) // 3. Format a prompt using the chat-template bypass (avoids // swift-jinja's broken Gemma 4 template renderer). let prompt = Gemma4PromptFormatter.userTurn("Hello, what is your name?") let tokens = await container.encode(prompt) let input = LMInput(tokens: MLXArray(tokens)) // 4. Generate. let stream = try await container.generate(input: input, parameters: .init(maxTokens: 200)) for await event in stream { if case .chunk(let text) = event { print(text, terminator: "") } } ``` -------------------------------- ### Gemma4TextConfiguration Layer Queries Source: https://context7.com/yejingyang8963-byte/swift-gemma4-core/llms.txt Use these extension methods on Gemma4TextConfiguration to determine layer types, KV sharing status, and donor layers without manual inspection. Ensure the configuration supports the current implementation before proceeding. ```swift import Gemma4SwiftCore // Determine the boundary between non-shared and KV-shared layers. let boundary = config.firstKvSharedLayerIdx // For E2B: 35 - 20 = 15 // Layers [0, 14] compute their own K/V; layers [15, 34] reuse from donors. // Walk the full layer list and print the attention class of each. for i in 0 ..< config.hiddenLayers { let type = config.isSlidingLayer(i) ? "sliding" : "full" let shared = config.isKvSharedLayer(i) ? " (KV-shared)" : "" let donor = config.kvDonorLayerIndex(forSharedLayer: i).map { " ← donor \($0)" } ?? "" print("Layer \(i): \(type)\(shared)\(donor)") } // Layer 0: sliding // Layer 4: full // ... // Layer 15: sliding (KV-shared) ← donor 14 // Layer 20: full (KV-shared) ← donor 4 // ... // Verify MoE guard before constructing the model manually. guard config.supportsCurrentImplementation else { fatalError("MoE Gemma 4 variants are not yet supported") } ``` -------------------------------- ### Add Gemma4SwiftCore to Swift Package Source: https://github.com/yejingyang8963-byte/swift-gemma4-core/blob/main/README.md Integrate Gemma4SwiftCore into your project by adding it as a dependency in your Package.swift file. Ensure your target includes the Gemma4SwiftCore product. ```swift dependencies: [ .package( url: "https://github.com/yejingyang8963-byte/Swift-gemma4-core.git", from: "0.1.0"), ], targets: [ .target( name: "YourApp", dependencies: [ .product(name: "Gemma4SwiftCore", package: "Swift-gemma4-core"), ]) ] ``` -------------------------------- ### Gemma4SwiftCore Module Constants Source: https://context7.com/yejingyang8963-byte/swift-gemma4-core/llms.txt Access module constants for package version and verified model ID for diagnostic logging and model identification. ```APIDOC ## Gemma4SwiftCore (module constants) Marker enum holding the package's identity and the verified HuggingFace model ID. Use `Gemma4SwiftCore.version` for diagnostic logging and `Gemma4SwiftCore.verifiedModelId` as the pre-validated model identifier, avoiding typos in model strings. ```swift import Gemma4SwiftCore // Print package version for diagnostics print("Gemma4SwiftCore v\(Gemma4SwiftCore.version)") // → "Gemma4SwiftCore v0.1.0" // Use the verified model ID (mlx-community/gemma-4-e2b-it-4bit) let modelId = Gemma4SwiftCore.verifiedModelId print("Model: \(modelId)") // → "Model: mlx-community/gemma-4-e2b-it-4bit" ``` ``` -------------------------------- ### List Untracked Files Source: https://github.com/yejingyang8963-byte/swift-gemma4-core/blob/main/PUSH_CHECKLIST.md Check for any untracked files in the repository. The output should be empty, indicating all files are either tracked or ignored. ```bash git status --short ``` -------------------------------- ### Verify README Header Author Source: https://github.com/yejingyang8963-byte/swift-gemma4-core/blob/main/PUSH_CHECKLIST.md Search the README file for the author's name to confirm it appears in the correct sections, such as the byline and author information. ```bash grep -i "Jingyang Ye" README.md ``` -------------------------------- ### Proportional RoPE Implementation Source: https://github.com/yejingyang8963-byte/swift-gemma4-core/blob/main/Sources/Gemma4SwiftCore/Documentation.docc/Architecture.md Highlights the custom implementation of Proportional RoPE, which differs from standard RoPE variants. This implementation is byte-for-byte compatible with Python's mlx_lm.models.rope_utils.ProportionalRoPE and is used for full-attention layers. ```swift Gemma4ProportionalRoPE ``` -------------------------------- ### Gemma4PromptFormatter.userTurn(_:) Source: https://context7.com/yejingyang8963-byte/swift-gemma4-core/llms.txt Formats a single user message into Gemma 4's chat protocol. This is the recommended format for production text generation. ```APIDOC ## Gemma4PromptFormatter.userTurn(_:) Formats a single user message into Gemma 4's `<|turn>` chat protocol without a system turn or chain-of-thought. This is the recommended format for production text generation where clean, instruction-following output is desired. Do **not** use `tokenizer.applyChatTemplate` — `swift-jinja` 1.x renders the Gemma 4 template incorrectly and drops 5 tokens. ```swift import Gemma4SwiftCore import MLX import MLXLMCommon // Format a plain user prompt. let formatted = Gemma4PromptFormatter.userTurn("Tell me a short story about a curious fox.") // Produces: // <|turn>user // Tell me a short story about a curious fox. // <|turn>model // // Encode with the model's tokenizer — special tokens are correctly resolved. let tokens = await container.encode(formatted) let input = LMInput(tokens: MLXArray(tokens)) // Stream the response. let stream = try await container.generate( input: input, parameters: GenerateParameters(maxTokens: 200, temperature: 0.8, topP: 0.95)) for await event in stream { if case .chunk(let text) = event { print(text, terminator: "") } } ``` ``` -------------------------------- ### Load and Inspect Gemma4TextConfiguration Source: https://context7.com/yejingyang8963-byte/swift-gemma4-core/llms.txt Load and parse a local `config.json` file into a `Gemma4TextConfiguration` struct. This struct decodes HuggingFace `config.json` for Gemma 4 text checkpoints, supporting both nested and flat configurations. It's primarily used by `Gemma4Registration` for model instantiation. ```swift import Gemma4SwiftCore import Foundation // Load and parse a local config.json. let configURL = URL(fileURLWithPath: "/path/to/model/config.json") let data = try Data(contentsOf: configURL) let config = try JSONDecoder().decode(Gemma4TextConfiguration.self, from: data) // Inspect architecture parameters (E2B values shown): print(config.hiddenLayers) // 35 print(config.hiddenSize) // 1536 print(config.attentionHeads) // 8 print(config.kvHeads) // 4 print(config.headDim) // 256 (sliding layers) print(config.globalHeadDim) // 512 (full-attention layers) print(config.numKvSharedLayers) // 20 (last 20 of 35 share KV) print(config.slidingWindow) // 1024 print(config.finalLogitSoftcapping) // Optional(30.0) print(config.supportsCurrentImplementation) // true (MoE not present) // Check layer-specific properties: print(config.headDimForLayer(0)) // 256 (sliding) print(config.headDimForLayer(4)) // 512 (full_attention) print(config.intermediateSizeForLayer(0)) // 6144 print(config.intermediateSizeForLayer(20)) // 12288 (KV-shared, double-wide MLP) print(config.isSlidingLayer(0)) // true print(config.isKvSharedLayer(34)) // true print(config.kvDonorLayerIndex(forSharedLayer: 34)) // Optional(14) ``` -------------------------------- ### Per-Layer Attention Configuration Source: https://github.com/yejingyang8963-byte/swift-gemma4-core/blob/main/Sources/Gemma4SwiftCore/Documentation.docc/Architecture.md Shows how the attention type and head dimension are determined per layer. The configuration specifies whether a layer uses 'sliding_attention' or 'full_attention', influencing the head dimension and projection sizes. ```swift config.layer_types[i] headDimForLayer(_:) ``` -------------------------------- ### Configure Git User Information Source: https://github.com/yejingyang8963-byte/swift-gemma4-core/blob/main/PUSH_CHECKLIST.md If the git log shows multiple authors, configure the local Git user name and email. This configuration only affects the current repository. ```bash git config user.name "Jingyang Ye" git config user.email "yejingyang8963@gmail.com" ``` -------------------------------- ### Swift RoPE Frequency Calculation Source: https://github.com/yejingyang8963-byte/swift-gemma4-core/blob/main/Sources/Gemma4SwiftCore/Documentation.docc/ProportionalRoPE.md Swift implementation of the RoPE frequency calculation, mirroring the Python logic for proportional rotation. ```swift // Swift port (Sources/Gemma4SwiftCore/Layers/Gemma4ProportionalRoPE.swift) let realCount = rotatedDims / 2 let padCount = (dims - rotatedDims) / 2 let exponentValues: [Float] = (0 ..< realCount).map { Float($0 * 2) / Float(dims) } let realFreqValues = exponentValues.map { factor * powf(base, $0) } let realFreqs = MLXArray(realFreqValues) let infFreqs = MLXArray([Float](repeating: .infinity, count: padCount)) self._freqs = MLX.concatenated([realFreqs, infFreqs], axis: 0) ``` -------------------------------- ### Check Git Log Authors Source: https://github.com/yejingyang8963-byte/swift-gemma4-core/blob/main/PUSH_CHECKLIST.md Verify that the Git log shows only one author. This helps ensure correct attribution and configuration. ```bash git log --format='%an <%ae>' | sort -u ``` -------------------------------- ### Register Gemma4TextModel with LLMModelFactory Source: https://context7.com/yejingyang8963-byte/swift-gemma4-core/llms.txt Register Gemma4TextModel with LLMModelFactory.shared.typeRegistry for 'gemma4' and 'gemma4_text' model types. This registration is idempotent and runs only once per process. ```swift import Gemma4SwiftCore import MLXLLM import MLXLMCommon // At app startup — must be called before any loadContainer call. // Returns a Task that can be awaited to confirm completion. await Gemma4Registration.registerIfNeeded().value // The registrationTask property lets you inspect or re-await from elsewhere. if let task = Gemma4Registration.registrationTask { await task.value // no-op if already completed } // Now load any HuggingFace Gemma 4 repo by ID. let container = try await LLMModelFactory.shared.loadContainer( configuration: ModelConfiguration(id: Gemma4SwiftCore.verifiedModelId)) // First run downloads ~1.5 GB; subsequent runs use the local cache (~6 s warm load). ``` -------------------------------- ### Check Git Remote URL Source: https://github.com/yejingyang8963-byte/swift-gemma4-core/blob/main/PUSH_CHECKLIST.md Verify the remote repository URL to ensure it points to the correct GitHub repository. Incorrect URLs can lead to pushing to the wrong location. ```bash git remote -v ``` -------------------------------- ### Gemma 4 vs Gemma 3n Configuration Fields Source: https://github.com/yejingyang8963-byte/swift-gemma4-core/blob/main/comparison/upstream_registry_audit.md This table details the configuration fields for Gemma 4 and Gemma 3n, illustrating their architectural differences. It shows fields present in one but not the other, emphasizing their distinct schemas. ```markdown | Config field | Gemma 4 | Gemma 3n | |---|:---:|:---:| | `hidden_size_per_layer_input` | ✅ | ✅ | | `vocab_size_per_layer_input` | ✅ | ✅ | | `use_double_wide_mlp` | ✅ | ❌ | | `global_head_dim` | ✅ | ❌ | | `num_kv_shared_layers` | ✅ | ❌ | | `attention_k_eq_v` | ✅ | ❌ | | `altup_num_inputs` | ❌ | ✅ | | `laurel_rank` | ❌ | ✅ | | `activation_sparsity_pattern` | ❌ | ✅ | ``` -------------------------------- ### Gemma 3 Text Configuration Error Source: https://github.com/yejingyang8963-byte/swift-gemma4-core/blob/main/docs/architecture.md This error occurs when attempting to use Gemma 3's text implementation for Gemma 4 due to missing configuration fields like 'laurel_rank'. ```text LLMModelFactory error: Missing field 'laurel_rank' in Gemma3TextConfiguration ``` -------------------------------- ### Python RoPE Frequency Formula Reference Source: https://github.com/yejingyang8963-byte/swift-gemma4-core/blob/main/Sources/Gemma4SwiftCore/Documentation.docc/ProportionalRoPE.md Reference implementation of the RoPE frequency calculation in Python, used for comparison. ```python # Python reference (mlx_lm/models/rope_utils.py:215-220) exponents = mx.arange(0, rotated_dims, 2, dtype=mx.float32) / dims freqs = mx.concatenate([ factor * (base ** exponents), mx.full(((dims - rotated_dims) // 2,), mx.inf), ]) ``` -------------------------------- ### Gemma4PromptFormatter.conversation(turns:bosFirst:) Source: https://context7.com/yejingyang8963-byte/swift-gemma4-core/llms.txt Formats a multi-turn conversation history, wrapping each `(role, content)` pair in `<|turn>{role}\n...` blocks and appending a trailing `<|turn>model\n` to invite the next assistant response. Roles are conventionally `"user"` and `"model"` in Gemma 4. ```APIDOC ## Gemma4PromptFormatter.conversation(turns:bosFirst:) ### Description Formats a multi-turn conversation history, wrapping each `(role, content)` pair in `<|turn>{role}\n...` blocks and appending a trailing `<|turn>model\n` to invite the next assistant response. Roles are conventionally `"user"` and `"model"` in Gemma 4. ### Parameters - **turns** (Array of Tuples) - An array of (role: String, content: String) tuples representing the conversation history. - **bosFirst** (Bool) - Whether to prepend the beginning-of-sequence token. ### Usage Example ```swift import Gemma4SwiftCore import MLX import MLXLMCommon // Build a two-turn conversation with prior history. let history: [(role: String, content: String)] = [ (role: "user", content: "Hello! What can you do?"), (role: "model", content: "I'm Gemma 4. I can answer questions and write stories."), (role: "user", content: "Great — write me a haiku about the ocean."), ] let formatted = Gemma4PromptFormatter.conversation(turns: history, bosFirst: true) ``` ### Output Example ``` <|turn>user Hello! What can you do? <|turn>model I'm Gemma 4. I can answer questions and write stories. <|turn>user Great — write me a haiku about the ocean. <|turn>model ``` ``` -------------------------------- ### Access Gemma4SwiftCore Package Constants Source: https://context7.com/yejingyang8963-byte/swift-gemma4-core/llms.txt Use Gemma4SwiftCore.version for diagnostic logging and Gemma4SwiftCore.verifiedModelId for the pre-validated HuggingFace model identifier. ```swift import Gemma4SwiftCore // Print package version for diagnostics print("Gemma4SwiftCore v\(Gemma4SwiftCore.version)") // → "Gemma4SwiftCore v0.1.0" // Use the verified model ID (mlx-community/gemma-4-e2b-it-4bit) let modelId = Gemma4SwiftCore.verifiedModelId print("Model: \(modelId)") // → "Model: mlx-community/gemma-4-e2b-it-4bit" ```