Closed ekinsdrow closed 1 month ago
Yikes! Thanks for letting us know, will look into this immediately.
As an aside: we have work planned to add literals into the language (which I see you're sorely missing here), but as a workaround, you might be able to use singly-valued enums for your types right now, ex:
enum BreadcrumbType {
Breadcrumb
}
class Breadcrumb {
type BreadcrumbType
...
}
(This unfortunately collides with the other issue you filed about the generated code for enum constants.)
Can you share the type definitions for Heading3, Paragraph, RichText, and ToDo?
After a bit of digging, we've found a number of scenarios that parse correctly and some that do not parse, but it gets hard to say how they should parse without digging into specifics, and I would prefer that whatever fix we ship for this be based on your actual scenario, not our own synthetic tests.
My best guess right now is that there's a parse error in column_list.children
that's rolling up into the union parsing decision for the type of Page.children[0]
, because per the testing I'm doing, that's the minimum required to trigger this, but I'd like to be sure that that's the case before doing it.
Hey! Thanks for your answer. I will take a look in singly-valued enums, thanks!
Here is defenitions of types which you asked -
/// ------------ Heading 3 ----------------
class Heading3 {
type string @description("Always heading_3")
heading_3 HeadingBody @description("Heading 3 block with rich text")
}
class HeadingBody {
rich_text RichText[] @description("The rich text content of the heading")
is_toggleable bool @description("Whether the heading is toggleable")
}
/// ------------ Paragraph ----------------
class Paragraph {
type string @description("Always paragraph")
paragraph ParagraphBody @description("Paragraph block with rich text")
}
class ParagraphBody {
rich_text RichText[] @description("The rich text displayed in the paragraph block")
children (Bookmark)[] @description("Optional nested child blocks for paragraph")
}
/// ------------ RichText ----------------
class RichText {
type string @description("Always text")
text RichTextText @description("The content of the rich text element")
}
/// ------------ To Do ----------------
class ToDo {
type string @description("Always to_do")
to_do ToDoBody @description("To-do block with checkbox and content")
}
class ToDoBody {
rich_text RichText[] @description("The text content of the to-do item")
checked bool? @description("Whether the to-do item is checked")
children (Paragraph | Callout | ImageFile)[] @description("Optional nested child blocks for to-do")
}
Now, it's start working very strange, now almost all my children became breadcrumb -
{
"object": "page",
"icon": {
"emoji": "📚"
},
"children": [
{
"type": "heading_1",
"breadcrumb": {}
},
{
"type": "paragraph",
"breadcrumb": {}
},
{
"type": "divider",
"divider": {}
},
{
"type": "heading_2",
"breadcrumb": {}
},
{
"type": "table",
"breadcrumb": {}
},
{
"type": "divider",
"divider": {}
},
{
"type": "heading_2",
"breadcrumb": {}
},
{
"type": "bulleted_list",
"breadcrumb": {}
},
{
"type": "divider",
"divider": {}
},
{
"type": "heading_2",
"breadcrumb": {}
},
{
"type": "paragraph",
"breadcrumb": {}
},
{
"type": "bulleted_list",
"breadcrumb": {}
},
{
"type": "divider",
"divider": {}
},
{
"type": "heading_2",
"breadcrumb": {}
},
{
"type": "bulleted_list",
"breadcrumb": {}
},
{
"type": "divider",
"divider": {}
},
{
"type": "heading_2",
"breadcrumb": {}
},
{
"type": "paragraph",
"breadcrumb": {}
},
{
"type": "quote",
"breadcrumb": {}
},
{
"type": "quote",
"breadcrumb": {}
}
]
}
OK, so I think the right approach for you is to use singly-valued enums like so (it definitely seems to work when testing); I've filed #949 for us to look into the other issues coming up here, but using singly-valued enums as a hack for literals will, I think, do the trick for you:
/// ------------ Heading 3 ----------------
class Heading3 {
type Heading3Type
heading_3 HeadingBody @description("Heading 3 block with rich text")
}
class HeadingBody {
rich_text RichText[] @description("The rich text content of the heading")
is_toggleable bool @description("Whether the heading is toggleable")
}
/// ------------ Paragraph ----------------
class Paragraph {
type ParagraphType
paragraph ParagraphBody @description("Paragraph block with rich text")
}
class ParagraphBody {
rich_text RichText[] @description("The rich text displayed in the paragraph block")
children (Bookmark)[] @description("Optional nested child blocks for paragraph")
}
/// ------------ RichText ----------------
class RichText {
type RichTextType
text RichTextText @description("The content of the rich text element")
}
/// ------------ To Do ----------------
class ToDo {
type ToDoType
to_do ToDoBody @description("To-do block with checkbox and content")
}
class ToDoBody {
rich_text RichText[] @description("The text content of the to-do item")
checked bool? @description("Whether the to-do item is checked")
children (Paragraph | Callout | ImageFile)[] @description("Optional nested child blocks for to-do")
}
// ---
class Page {
type PageType
object string @description("Always page")
icon Icon @description("Icon of page")
children (Bookmark | Breadcrumb | BulletedListItem | Callout | Code | ColumnList | Divider | Embed | Equation | File | Heading1 | Heading2 | Heading3 | ImageFile | NumberedListItem | Paragraph | PDF | Quote | Table | TableOfContents | ToDo | Toggle | Video)[] @description("Some blocks of the page")
}
enum BookmarkType {
Bookmark @alias("bookmark")
}
enum BreadcrumbType {
Breadcrumb @alias("breadcrumb")
}
enum BulletedListItemType {
BulletedListItem @alias("bulleted_list_item")
}
enum CalloutType {
Callout @alias("callout")
}
enum CodeType {
Code @alias("code")
}
enum ColumnListType {
ColumnList @alias("column_list")
}
enum DividerType {
Divider @alias("divider")
}
enum EmbedType {
Embed @alias("embed")
}
enum EquationType {
Equation @alias("equation")
}
enum FileType {
File @alias("file")
}
enum Heading1Type {
Heading1 @alias("heading1")
}
enum Heading2Type {
Heading2 @alias("heading2")
}
enum Heading3Type {
Heading3 @alias("heading3")
}
enum ImageFileType {
ImageFile @alias("image_file")
}
enum NumberedListItemType {
NumberedListItem @alias("numbered_list_item")
}
enum ParagraphType {
Paragraph @alias("paragraph")
}
enum PDFType {
PDF @alias("pdf")
}
enum QuoteType {
Quote @alias("quote")
}
enum RichTextType {
RichText @alias("rich_text")
}
enum TableType {
Table @alias("table")
}
enum TableOfContentsType {
TableOfContents @alias("table_of_contents")
}
enum ToDoType {
ToDo @alias("to_do")
}
enum ToggleType {
Toggle @alias("toggle")
}
enum VideoType {
Video @alias("video")
}
@ekinsdrow I think this issue is fixed in 0.56+.
I added your specific unit test into our repo, and it appears to work well.
Common description
I have encountered an issue where Baml parses the response from the LLM incorrectly. Specifically, it seems that one block type is being incorrectly converted into another block type in the response.
Issue
The
column_list
block from the LLM response is incorrectly converted to abreadcrumb
block in the Baml response. The configuration shows that these blocks should remain distinct, but for some reason, Baml is changing one type of block to another.Expected Behavior
Baml should parse the LLM response correctly, preserving the block types and structure as provided by the LLM response. The column_list block should not be converted into a breadcrumb.
Part of my configuration
LLM response
Baml parsing reponse