Skip to content

Commit 48bf82f

Browse files
committed
Support for list in list of custom objects
1 parent 8629a15 commit 48bf82f

File tree

4 files changed

+80
-51
lines changed

4 files changed

+80
-51
lines changed

tests/test_parser.py

Lines changed: 49 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -288,12 +288,12 @@ def test_parse_subtype_output(self):
288288
STRING 1: s1
289289
STRING 2: s2
290290
STRING 3: s3
291-
ITEM SUBTITLE 1: subtitle one
292-
ITEM DESCRIPTION 1: description one
293-
ITEM ABSTRACT 1: Just an abstract...
294-
ITEM SUBTITLE 2: subtitle two
295-
ITEM DESCRIPTION 2: Description TWO
296-
ITEM ABSTRACT 2: More abstract...
291+
ITEM 1 SUBTITLE: subtitle one
292+
ITEM 1 DESCRIPTION: description one
293+
ITEM 1 ABSTRACT: Just an abstract...
294+
ITEM 2 SUBTITLE: subtitle two
295+
ITEM 2 DESCRIPTION: Description TWO
296+
ITEM 2 ABSTRACT: More abstract...
297297
298298
SUBITEM TITLE: A subitem title (!!)
299299
@@ -343,7 +343,8 @@ class InnerElement(BaseLLMArrayElement):
343343
description: str | None = LLMArrayElementOutput(lambda pos: f"Put the {pos.ordinal} item description here")
344344
abstract: str = LLMArrayElementOutput(lambda _: "...", multiline=True)
345345
inner_item: InnerItem
346-
# inner_elements: list[InnerElement] = LLMArrayOutput(2, instruction=lambda _: "...")
346+
inner_elements: list[InnerElement] = LLMArrayOutput(2, instruction=lambda _: "...")
347+
multiline_text: list[str] = LLMArrayOutput((0, None), lambda _: "...", multiline=True)
347348

348349
class DirectItem(BaseLLMResponse):
349350
class InnerDirectElement(BaseLLMArrayElement):
@@ -362,25 +363,38 @@ def test_parse_ultra_subtype_output(self):
362363
363364
SUBITEM TITLE: subtitle
364365
disregarded!
365-
SUBITEM X SUBTITLE 1: sub1
366+
SUBITEM X 1 SUBTITLE: sub1
366367
? also disregarded ?
367-
SUBITEM X SUBTITLE 2: sub2
368-
369-
ITEM SUBTITLE 1: First item subtitle
370-
ITEM DESCRIPTION 1: first descr.
371-
ITEM ABSTRACT 1: Jsut some random abstract
372-
ITEM INNER ITEM TITLE 1: INNER TITLE 1
373-
ITEM INNER ITEM DESCRIPTION 1: DESCription 1
374-
ITEM INNER ELEMENT VALUE 1: 1.0
375-
ITEM INNER ELEMENT IS ACCURATE 1: yes
376-
ITEM INNER ELEMENT VALUE 2: 3.14
377-
ITEM INNER ELEMENT IS ACCURATE 2: False
378-
379-
ITEM SUBTITLE 2: Second item subtitle
380-
ITEM ABSTRACT 2: Another abstract but this time
368+
SUBITEM X 2 SUBTITLE: sub2
369+
370+
ITEM 1 SUBTITLE: First item subtitle
371+
ITEM 1 DESCRIPTION: first descr.
372+
ITEM 1 ABSTRACT: Jsut some random abstract
373+
ITEM 1 INNER ITEM TITLE: INNER TITLE 1
374+
ITEM 1 INNER ITEM DESCRIPTION: DESCription 1
375+
ITEM 1 INNER ELEMENT 1 VALUE: 1.0
376+
ITEM 1 INNER ELEMENT 1 IS ACCURATE: yes
377+
ITEM 1 INNER ELEMENT 2 VALUE: 3.14
378+
ITEM 1 INNER ELEMENT 2 IS ACCURATE: False
379+
ITEM 1 MULTILINE TEXT 1: line 1
380+
line 2
381+
line 3
382+
ITEM 1 MULTILINE TEXT 2: line 4
383+
line 5
384+
line 6
385+
ITEM 1 MULTILINE TEXT 3: line 7
386+
line 8
387+
line 9
388+
389+
ITEM 2 SUBTITLE: Second item subtitle
390+
ITEM 2 ABSTRACT: Another abstract but this time
381391
with multiple lines
382-
ITEM INNER ITEM TITLE 2: tt2
383-
ITEM INNER ITEM DESCRIPTION 2: dd2
392+
ITEM 2 INNER ITEM TITLE: tt2
393+
ITEM 2 INNER ITEM DESCRIPTION: dd2
394+
ITEM 2 INNER ELEMENT 1 VALUE: 2.0
395+
ITEM 2 INNER ELEMENT 1 IS ACCURATE: no
396+
ITEM 2 INNER ELEMENT 2 VALUE: 8.958
397+
ITEM 2 INNER ELEMENT 2 IS ACCURATE: True
384398
"""
385399
parsed_output = self.UltraSubtypeTestOutput.parse_response(completion_output)
386400
assert parsed_output.title == "Main head title"
@@ -395,11 +409,22 @@ def test_parse_ultra_subtype_output(self):
395409
assert parsed_output.items[0].abstract == "Jsut some random abstract"
396410
assert parsed_output.items[0].inner_item.title == "INNER TITLE 1"
397411
assert parsed_output.items[0].inner_item.description == "DESCription 1"
412+
assert len(parsed_output.items[0].inner_elements) == 2
413+
assert parsed_output.items[0].inner_elements[0].value == 1.0
414+
assert parsed_output.items[0].inner_elements[0].is_accurate == True
415+
assert parsed_output.items[0].inner_elements[1].value == 3.14
416+
assert parsed_output.items[0].inner_elements[1].is_accurate == False
417+
assert parsed_output.items[0].multiline_text == ["line 1\nline 2\nline 3", "line 4\nline 5\nline 6", "line 7\nline 8\nline 9"]
398418

399419
assert parsed_output.items[1].subtitle == "Second item subtitle"
400420
assert parsed_output.items[1].description is None
401421
assert parsed_output.items[1].abstract == "Another abstract but this time\nwith multiple lines"
402422
assert parsed_output.items[1].inner_item.title == "tt2"
403423
assert parsed_output.items[1].inner_item.description == "dd2"
424+
assert len(parsed_output.items[1].inner_elements) == 2
425+
assert parsed_output.items[1].inner_elements[0].value == 2.0
426+
assert parsed_output.items[1].inner_elements[0].is_accurate == False
427+
assert parsed_output.items[1].inner_elements[1].value == 8.958
428+
assert parsed_output.items[1].inner_elements[1].is_accurate == True
404429

405430
# endregion

tests/test_prompt.py

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -129,12 +129,12 @@ def test_subtype_output_fields(self):
129129
STRING 2: <Put the second string here>
130130
...
131131
132-
ITEM SUBTITLE 1: <Put the first subtitle here>
133-
ITEM DESCRIPTION 1: <Put the first item description here>
134-
ITEM ABSTRACT 1: <Some instruction>
135-
ITEM SUBTITLE 2: <Put the second subtitle here>
136-
ITEM DESCRIPTION 2: <Put the second item description here>
137-
ITEM ABSTRACT 2: <Some instruction>
132+
ITEM 1 SUBTITLE: <Put the first subtitle here>
133+
ITEM 1 DESCRIPTION: <Put the first item description here>
134+
ITEM 1 ABSTRACT: <Some instruction>
135+
ITEM 2 SUBTITLE: <Put the second subtitle here>
136+
ITEM 2 DESCRIPTION: <Put the second item description here>
137+
ITEM 2 ABSTRACT: <Some instruction>
138138
...
139139
140140
SUBITEM TITLE: <Put the title here>
@@ -180,28 +180,28 @@ def test_ultra_subtype_output_fields(self):
180180
TITLE: <Put the title here>
181181
182182
SUBITEM TITLE: <Put the title here>
183-
SUBITEM X SUBTITLE 1: <Put the first subtitle here>
184-
SUBITEM X SUBTITLE 2: <Put the second subtitle here>
183+
SUBITEM X 1 SUBTITLE: <Put the first subtitle here>
184+
SUBITEM X 2 SUBTITLE: <Put the second subtitle here>
185185
...
186186
187-
ITEM SUBTITLE 1: <Put the first subtitle here>
188-
ITEM DESCRIPTION 1: <Put the first description here>
189-
ITEM ABSTRACT 1: <Put the first abstract here>
187+
ITEM 1 SUBTITLE: <Put the first subtitle here>
188+
ITEM 1 DESCRIPTION: <Put the first description here>
189+
ITEM 1 ABSTRACT: <Put the first abstract here>
190190
191-
ITEM INNER ITEM TITLE 1: <Put the title here>
192-
ITEM INNER ITEM DESCRIPTION 1: <Put the description here>
191+
ITEM 1 INNER ITEM TITLE: <Put the title here>
192+
ITEM 1 INNER ITEM DESCRIPTION: <Put the description here>
193193
194-
ITEM INNER ELEMENT VALUE 1: <Put the first value here>
195-
ITEM INNER ELEMENT VALUE 2: <Put the second value here>
196-
ITEM SUBTITLE 2: <Put the second subtitle here>
197-
ITEM DESCRIPTION 2: <Put the second description here>
198-
ITEM ABSTRACT 2: <Put the second abstract here>
194+
ITEM 1 INNER ELEMENT 1 VALUE: <Put the first value here>
195+
ITEM 1 INNER ELEMENT 2 VALUE: <Put the second value here>
196+
ITEM 2 SUBTITLE: <Put the second subtitle here>
197+
ITEM 2 DESCRIPTION: <Put the second description here>
198+
ITEM 2 ABSTRACT: <Put the second abstract here>
199199
200-
ITEM INNER ITEM TITLE 2: <Put the title here>
201-
ITEM INNER ITEM DESCRIPTION 2: <Put the description here>
200+
ITEM 2 INNER ITEM TITLE: <Put the title here>
201+
ITEM 2 INNER ITEM DESCRIPTION: <Put the description here>
202202
203-
ITEM INNER ELEMENT VALUE 1: <Put the first value here>
204-
ITEM INNER ELEMENT VALUE 2: <Put the second value here>
203+
ITEM 2 INNER ELEMENT 1 VALUE: <Put the first value here>
204+
ITEM 2 INNER ELEMENT 2 VALUE: <Put the second value here>
205205
...
206206
\"""
207207
""".strip()

typegpt/parser.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ def _regex_for_field(self, field: LLMFieldInfo) -> str:
4848
count_regex = "\\d{1,3}"
4949

5050
if field_type := if_array_element_list_type(field.type_):
51-
return rf"(?:^|\n){field.name} (?P<subfield_name>((?!:|\n)[\S ])+) (?P<i>{count_regex}): ?(?P<content>({exclusion_cases_regex}[\s\S])+)"
51+
return rf"(?:^|\n){field.name} (?P<i>{count_regex}) (?P<subfield_name>((?!:|\n)[\S ])+): ?(?P<content>({exclusion_cases_regex}[\s\S])+)"
5252
else:
5353
return rf"(?:^|\n){field.name} {count_regex}: ?(?P<content>({exclusion_cases_regex}[\s\S])+)"
5454

typegpt/prompt_builder.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,12 @@ def _generate_array(self, field: LLMFieldInfo, info: LLMArrayOutputInfo) -> str:
1515

1616
if element_type := if_array_element_list_type(field.type_):
1717
subfields = list(element_type.__fields__.values())
18-
subprompt_factory = OutputPromptFactory(subfields, name_prefixes=self.name_prefixes + [field.name])
19-
examples = [subprompt_factory._generate_schema(offset=i + 1) for i in range(max_count)]
18+
# subprompt_factory = OutputPromptFactory(subfields, name_prefixes=self.name_prefixes + [field.name])
19+
# examples = [subprompt_factory._generate_schema(offset=i + 1) for i in range(max_count)]
20+
examples = [
21+
OutputPromptFactory(subfields, name_prefixes=self.name_prefixes + [field.name + f" {i+1}"])._generate_schema(offset=i + 1)
22+
for i in range(max_count)
23+
]
2024
else:
2125
field_name = " ".join(self.name_prefixes + [field.name])
2226
examples = [f"{field_name} {i+1}: <{info.instruction(ExamplePosition(i+1))}>" for i in range(max_count)]
@@ -31,8 +35,8 @@ def _generate_schema(self, offset: int = 0) -> str:
3135

3236
for field in self.fields:
3337
field_name = " ".join(self.name_prefixes + [field.name])
34-
if offset > 0:
35-
field_name += f" {offset}"
38+
# if offset > 0:
39+
# field_name += f" {offset}"
3640

3741
if isinstance(field.info, LLMOutputInfo):
3842
if field_type := if_response_type(field.type_):

0 commit comments

Comments
 (0)