diff --git a/Sources/AnyLanguageModel/Shared/StructuredGeneration.swift b/Sources/AnyLanguageModel/Shared/StructuredGeneration.swift index aae832e2..eb45bd93 100644 --- a/Sources/AnyLanguageModel/Shared/StructuredGeneration.swift +++ b/Sources/AnyLanguageModel/Shared/StructuredGeneration.swift @@ -46,6 +46,8 @@ private final class StringTokenCache: @unchecked Sendable { } private let tokensByKey = Locked<[Key: Set]>([:]) + private let integerTokensByKey = Locked<[Key: Set]>([:]) + private let decimalTokensByKey = Locked<[Key: Set]>([:]) func tokens(for key: Key) -> Set? { tokensByKey.withLock { $0[key] } @@ -54,6 +56,22 @@ private final class StringTokenCache: @unchecked Sendable { func store(_ tokens: Set, for key: Key) { tokensByKey.withLock { $0[key] = tokens } } + + func integerTokens(for key: Key) -> Set? { + integerTokensByKey.withLock { $0[key] } + } + + func storeIntegerTokens(_ tokens: Set, for key: Key) { + integerTokensByKey.withLock { $0[key] = tokens } + } + + func decimalTokens(for key: Key) -> Set? { + decimalTokensByKey.withLock { $0[key] } + } + + func storeDecimalTokens(_ tokens: Set, for key: Key) { + decimalTokensByKey.withLock { $0[key] = tokens } + } } // MARK: - JSON Generator @@ -194,6 +212,11 @@ struct ConstrainedJSONGenerator { } private static func buildValidIntegerTokens(backend: Backend) -> Set { + let cacheKey = stringTokenCacheKey(for: backend) + if let cached = StringTokenCache.shared.integerTokens(for: cacheKey) { + return cached + } + var allowed = Set() for token in 0 ..< backend.vocabSize { if backend.isSpecialToken(token) { continue } @@ -204,10 +227,17 @@ struct ConstrainedJSONGenerator { allowed.insert(token) } } + + StringTokenCache.shared.storeIntegerTokens(allowed, for: cacheKey) return allowed } private static func buildValidDecimalTokens(backend: Backend) -> Set { + let cacheKey = stringTokenCacheKey(for: backend) + if let cached = StringTokenCache.shared.decimalTokens(for: cacheKey) { + return cached + } + var allowed = Set() for token in 0 ..< backend.vocabSize { if backend.isSpecialToken(token) { continue } @@ -218,6 +248,8 @@ struct ConstrainedJSONGenerator { allowed.insert(token) } } + + StringTokenCache.shared.storeDecimalTokens(allowed, for: cacheKey) return allowed }