Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions Package.resolved

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ let package = Package(
),
.package(
url: "https://github.com/shareup/mlx-swift-lm",
from: "0.0.16"
revision: "d414b738a56f6a0f92800f0ff1f663167bb0f871"
),
.package(
url: "https://github.com/DePasqualeOrg/swift-tokenizers",
Expand Down
20 changes: 8 additions & 12 deletions Sources/SHLLM/LLM.swift
Original file line number Diff line number Diff line change
Expand Up @@ -633,12 +633,7 @@ extension LLM where Model == Gemma4 {
/// **gemma-4-e2b** and **gemma-4-e4b**
///
/// To enable thinking, set
/// `UserInput(additionalContext: ["enable_thinking": true])`
/// and add `<|think|>` to the **beginning** and **end** of
/// the system prompt. (The documentation says to just add it to
/// the beginning of the system prompt, but testing has shown it
/// to be more reliable when added to the beginning and end of the
/// system prompt.
/// `UserInput(additionalContext: ["enable_thinking": true])`.
///
/// https://huggingface.co/google/gemma-4-12B-it#2-thinking-mode-configuration
public static func gemma4(
Expand Down Expand Up @@ -701,12 +696,7 @@ extension LLM where Model == Gemma4Unified {
/// **gemma-4-12b**
///
/// To enable thinking, set
/// `UserInput(additionalContext: ["enable_thinking": true])`
/// and add `<|think|>` to the **beginning** and **end** of
/// the system prompt. (The documentation says to just add it to
/// the beginning of the system prompt, but testing has shown it
/// to be more reliable when added to the beginning and end of the
/// system prompt.
/// `UserInput(additionalContext: ["enable_thinking": true])`.
///
Comment on lines 696 to 700
/// https://huggingface.co/google/gemma-4-12B-it#2-thinking-mode-configuration
public static func gemma4Unified(
Expand All @@ -717,6 +707,12 @@ extension LLM where Model == Gemma4Unified {
maxOutputTokenCount: Int? = nil
) throws -> LLM<Gemma4Unified> {
try SHLLM.assertSupportedDevice
var input = input
var additionalContext = input.additionalContext ?? [:]
if additionalContext["enable_thinking"] == nil {
additionalContext["enable_thinking"] = true
}
input.additionalContext = additionalContext
Comment on lines 709 to +715
return .init(
directory: directory,
input: input,
Expand Down
8 changes: 1 addition & 7 deletions Tests/SHLLMTests/Models/Gemma4-12BTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ struct Gemma4_12BTests {
let input = UserInput(
chat: [
.system(
"You are a weather assistant who must use the get_current_weather tool to fetch weather data for any location the user asks about.<|think|>"
"You are a weather assistant who must use the get_current_weather tool to fetch weather data for any location the user asks about."
),
.user("What is the weather in Paris, France?"),
],
Expand Down Expand Up @@ -147,10 +147,8 @@ struct Gemma4_12BTests {

let chat: [Chat.Message] = [
.system("""
<|think|>
You are a helpful assistant that can provide stock prices.
When asked for a stock price, you must use the get_stock_price tool.
<|think|>
"""),
.user("What is the price of AAPL?"),
]
Expand All @@ -166,7 +164,6 @@ struct Gemma4_12BTests {
let toolCall1 = try #require(toolCallsOpt1?.first)

Swift.print("<thinking>\(reasoning1 ?? "")</thinking>\n\(text1 ?? "")")
#expect(reasoning1 != nil)
#expect(text1 == nil)
#expect(toolCall1.function.name == "get_stock_price")
#expect(toolCall1.function.arguments["symbol"] == .string("AAPL"))
Expand Down Expand Up @@ -194,10 +191,8 @@ struct Gemma4_12BTests {

let chat: [Chat.Message] = [
.system("""
<|think|>
You are an email assistant. When asked to read an email, call mail_read exactly once.
After the tool result is provided, reply with the email subject exactly and do not call tools again.
<|think|>
"""),
.user("Read email 158348 from account me@example.com in mailbox INBOX."),
]
Expand All @@ -213,7 +208,6 @@ struct Gemma4_12BTests {
let toolCall1 = try #require(toolCallsOpt1?.first)

Swift.print("<thinking>\(reasoning1 ?? "")</thinking>\n\(text1 ?? "")")
#expect(reasoning1 != nil)
#expect(text1 == nil)
#expect(toolCall1.function.name == "mail_read")
#expect(toolCall1.function.arguments["account"] == .string("me@example.com"))
Expand Down
8 changes: 1 addition & 7 deletions Tests/SHLLMTests/Models/Gemma4-E2BTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ struct Gemma4_E2BTests {
let input = UserInput(
chat: [
.system(
"You are a weather assistant who must use the get_current_weather tool to fetch weather data for any location the user asks about.<|think|>"
"You are a weather assistant who must use the get_current_weather tool to fetch weather data for any location the user asks about."
),
.user("What is the weather in Paris, France?"),
],
Expand Down Expand Up @@ -147,10 +147,8 @@ struct Gemma4_E2BTests {

let chat: [Chat.Message] = [
.system("""
<|think|>
You are a helpful assistant that can provide stock prices.
When asked for a stock price, you must use the get_stock_price tool.
<|think|>
"""),
.user("What is the price of AAPL?"),
]
Expand All @@ -166,7 +164,6 @@ struct Gemma4_E2BTests {
let toolCall1 = try #require(toolCallsOpt1?.first)

Swift.print("<thinking>\(reasoning1 ?? "")</thinking>\n\(text1 ?? "")")
#expect(reasoning1 != nil)
#expect(text1 == nil)
#expect(toolCall1.function.name == "get_stock_price")
#expect(toolCall1.function.arguments["symbol"] == .string("AAPL"))
Expand Down Expand Up @@ -194,10 +191,8 @@ struct Gemma4_E2BTests {

let chat: [Chat.Message] = [
.system("""
<|think|>
You are an email assistant. When asked to read an email, call mail_read exactly once.
After the tool result is provided, reply with the email subject exactly and do not call tools again.
<|think|>
"""),
.user("Read email 158348 from account me@example.com in mailbox INBOX."),
]
Expand All @@ -213,7 +208,6 @@ struct Gemma4_E2BTests {
let toolCall1 = try #require(toolCallsOpt1?.first)

Swift.print("<thinking>\(reasoning1 ?? "")</thinking>\n\(text1 ?? "")")
#expect(reasoning1 != nil)
#expect(text1 == nil)
#expect(toolCall1.function.name == "mail_read")
#expect(toolCall1.function.arguments["account"] == .string("me@example.com"))
Expand Down
8 changes: 1 addition & 7 deletions Tests/SHLLMTests/Models/Gemma4-E4BTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ struct Gemma4_E4BTests {
let input = UserInput(
chat: [
.system(
"You are a weather assistant who must use the get_current_weather tool to fetch weather data for any location the user asks about.<|think|>"
"You are a weather assistant who must use the get_current_weather tool to fetch weather data for any location the user asks about."
),
.user("What is the weather in Paris, France?"),
],
Expand Down Expand Up @@ -147,10 +147,8 @@ struct Gemma4_E4BTests {

let chat: [Chat.Message] = [
.system("""
<|think|>
You are a helpful assistant that can provide stock prices.
When asked for a stock price, you must use the get_stock_price tool.
<|think|>
"""),
.user("What is the price of AAPL?"),
]
Expand All @@ -166,7 +164,6 @@ struct Gemma4_E4BTests {
let toolCall1 = try #require(toolCallsOpt1?.first)

Swift.print("<thinking>\(reasoning1 ?? "")</thinking>\n\(text1 ?? "")")
#expect(reasoning1 != nil)
#expect(text1 == nil)
#expect(toolCall1.function.name == "get_stock_price")
#expect(toolCall1.function.arguments["symbol"] == .string("AAPL"))
Expand Down Expand Up @@ -194,10 +191,8 @@ struct Gemma4_E4BTests {

let chat: [Chat.Message] = [
.system("""
<|think|>
You are an email assistant. When asked to read an email, call mail_read exactly once.
After the tool result is provided, reply with the email subject exactly and do not call tools again.
<|think|>
"""),
.user("Read email 158348 from account me@example.com in mailbox INBOX."),
]
Expand All @@ -213,7 +208,6 @@ struct Gemma4_E4BTests {
let toolCall1 = try #require(toolCallsOpt1?.first)

Swift.print("<thinking>\(reasoning1 ?? "")</thinking>\n\(text1 ?? "")")
#expect(reasoning1 != nil)
#expect(text1 == nil)
#expect(toolCall1.function.name == "mail_read")
#expect(toolCall1.function.arguments["account"] == .string("me@example.com"))
Expand Down
Loading