Skip to content

Name inline objects and choices for Foundation Models - #339

Open
akbashev wants to merge 15 commits into
huggingface:mainfrom
akbashev:fix/fm-inline-object-names
Open

akbashev wants to merge 15 commits into
huggingface:mainfrom
akbashev:fix/fm-inline-object-names

Conversation

@akbashev

Copy link
Copy Markdown
Contributor

Builds on #337 and #338. Only the last commit, "Name inline objects and choices for Foundation Models", belongs to this PR.

Foundation Models refers to every object and choice by its name. One written in place, as a schema read from JSON has them, was named "", which refers to nothing. Creating the session then failed with "Reference to undefined symbol: #", before the model read a word.

Each one is now named by where it sits in the schema.

Foundation Models generates an object's properties in its schema's order.
The conversion went through JSONValue and JSONSchema, whose decoding loses
key order, so properties reached the model shuffled: a container's items
could come before what the container is, and generation ran away nesting.
Convert straight from GenerationSchema's nodes, which keep propertyOrder.
Foundation Models refers to every object and choice by its name. One
written in place, as a schema read from JSON has them, was named "", which
refers to nothing: creating the session failed with "Reference to undefined
symbol: #", before the model read a word. Name each by where it sits.
A schema that lists values with a description each, as oneOf constants,
decoded as a plain string: the choices were lost, and the model could write
anything. oneOf asks for exactly one choice, which generating one value
always gives, so it reads as anyOf.
@mattt

mattt commented Oct 17, 2026

Copy link
Copy Markdown
Collaborator

Thanks, @akbashev. One problem with naming by path: every definition starts with an empty path, same as the root. So an inline object x at the root and an inline object x inside definition A both end up named "x", and one of them loses its properties. Could you start each definition's path with its name, and keep the root's names distinct?

Also, swift format lint --strict flags a long line at InlineObjectNamesFoundationModelsTests.swift:34.

Converting from GenerationSchema's nodes, a named definition that is only
a reference, such as a one-choice anyOf, dropped its name as the JSONSchema
path did before huggingface#332, so the references to it were undefined. It now stays
a named schema whose one choice is the reference. An integer's bounds
become the whole numbers within them, and a bound no Int holds, such as a
non-finite or very large one, sets no guide instead of trapping. The
unused appearInOrder test helper is gone.
Every definition's inline objects and choices were named from an empty
path, as the root's are, so an inline object x at the root and one in
definition A were both named "x", and one lost its properties. A
definition's names now start with its own name, and the root's with a name
no definition has.
The stand-in value for a number with no usable output took Int(minimum),
which traps on a minimum that isn't finite or that Int can't hold. It's
now the smallest whole number the minimum allows, or the nearest Int when
there's none; a stand-in decimal ignores a minimum that isn't finite.
@akbashev

Copy link
Copy Markdown
Contributor Author

Thanks, @mattt. A definition's inline objects and choices are now named starting from the definition's own name, and the root's start from a name no definition uses. sameInlineNameInRootAndDefinitionStaysApart fails without the fix: definition A's x lost its properties. The long line is fixed too.

@mattt

mattt commented Oct 17, 2026

Copy link
Copy Markdown
Collaborator

Thanks, @akbashev. #337 and #338 are in. This one fails the watchOS build (watchOS availability has been a rake we've all been stepping on lately): InlineObjectNamesFoundationModelsTests.swift:65 uses SystemLanguageModel, which isn't available on watchOS. Could you guard that test, and bring in main?

@akbashev

akbashev commented Oct 18, 2026 •

Copy link
Copy Markdown
Contributor Author

@mattt
Guarded the session test with #if !os(watchOS), as FoundationLanguageModelTests does, and merged main. The watchOS Simulator test build passes now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants