### ----------------------------------------------------
### -- LLM::Functions
### -- Licenses: Artistic-2.0
### -- Authors: Anton Antonov
### -- File: docs/Workflows-with-LLM-functions_woven.md
### ----------------------------------------------------
### -- Chunk 2 of 3
S + 3O2         |
# +-----------+-----------+------------+-----------+-----------+------------+------------+--------------------------+
```

### Alternative workflow and solution

Assume that we only wanted to extract the chemical components together with their molecular masses
from the LLM generated equations.

Then we:
- Use the function `chem-component` defined above as a sub-parser in the retrieval LLM-function
- Pick `Pair` objects from the LLM function result 

Here is the LLM function:

```perl6 
my &cfnp = llm-function(
        { "Give $^a chemical stoichiometry formulas that includes $^b." },
        llm-evaluator => 'OpenAI', form => sub-parser(&chem-component));
```
```
# -> **@args, *%args { #`(Block|6266929579144) ... }
```

Here is an invocation:

```perl6
my $chemRes2 = &cfnp(4, 'sulfur and hydrogen');
```
```
# [
# 
# 1.  SO2 => 64.058  +  H2 => 4.032  →  S => 32.06  +  H2O => 36.03  
# 2.  H2S => 34.076  +  O2 => 63.996  →  SO2 => 64.058  +  H2O => 36.03  
# 3.  H2S => 34.076  +  O2 => 95.994  →  SO3 => 80.057  +  H2O => 36.03  
# 4.  H2S => 68.152  +  O2 => 95.994  →  SO2 => 128.116  +  H2O => 36.03]
```

Here we filter result's elements:

```perl6
$chemRes2.grep(* ~~ Pair)
```
```
# (SO2 => 64.058 H2 => 4.032 S => 32.06 H2O => 36.03 H2S => 34.076 O2 => 63.996 SO2 => 64.058 H2O => 36.03 H2S => 34.076 O2 => 95.994 SO3 => 80.057 H2O => 36.03 H2S => 68.152 O2 => 95.994 SO2 => 128.116 H2O => 36.03)
```

### Exercise questions

- What is a good approach to evaluate the ability of LLMs to respect the conservation of mass law?
- Is it better for that evaluation to use predominantly Raku code or mostly LLM-functions?

------

## Making (embedded) Mermaid diagrams

**Workflow:** We want to quickly initiate
[Mermaid-JS](https://mermaid.js.org)
code for specific types of diagrams.

Here is an LLM function for generating a Mermaid JS spec:

```perl6 
my &fmmd = llm-function({ "Generate the Mermaid-JS code of a $^a for $^b." })
```
```
# -> **@args, *%args { #`(Block|6266929632128) ... }
```

Here we request to get the code of pie chart for the continent sizes:

```perl6 , results=asis
my $mmdRes = &fmmd("pie chart", "relative continent sizes")
```
pie 
    "Africa" : 24.3,
    "Asia" : 29.2,
    "Europe" : 10.8,
    "North America" : 16.5,
    "Oceania" : 0.4,
    "South America" : 17.8


Here, "just in case", we normalize the numbers of the result and "dump" the code as Markdown code cell:

```perl6 , output.prompt=NONE, output.lang=mermaid
$mmdRes.subst(:g, '%', '').subst(:g, ',', '').subst("{'`' x 3}mermaid", '').subst("{'`' x 3}", '')
```
```mermaid
pie 
    "Africa" : 24.3
    "Asia" : 29.2
    "Europe" : 10.8
    "North America" : 16.5
    "Oceania" : 0.4
    "South America" : 17.8
```

Here is a flow chart request:

```perl6 , results=asis
&fmmd("flow chart", "going to work in the morning avoiding traffic jams and reacting to weather")
```
```mermaid
graph TD
A[Check Traffic & Weather] --> B[Leave Early?]
B --> |Yes| C[Check Alternate Route]
B --> |No| D[Go Normal Route]
C --> |No Traffic Jams| E[Leave]
C --> |Traffic Jams| F[Check Other Routes]
F --> |No Traffic Jams| E
F --> |Traffic Jams| G[Leave at Later Time]
G --> |Weather Permitting| E
G --> |Bad Weather| H[Look for Other Options]


### Exercise questions

- What changes of the code in this section should be made in order to produce Plant-UML specs?

------

## Named entity recognition

**Workflow:** We want to download text from the Web, extract the names of certain types of entities from it,
and visualize relationships between them.

For example, we might want to extract all album names and their release dates from
a biographical web page of a certain music artist, and make a timeline plot.


```raku
my &fner = llm-function({"Extract $^a from the text: $^b . Give the result in a JSON format"},                     
                        llm-evaluator => 'PaLM', 
                        form => sub-parser('JSON'))
```
```
# -> **@args, *%args { #`(Block|6266929673952) ... }
```

Here is a way to get a biography and discography text data of a music artist from Wikipedia:

```raku, eval=FALSE
my $url = 'https://en.wikipedia.org/wiki/Sinéad_O%27Connor';
my $response = HTTP::Tiny.new.get: $url;            

die "Failed!\n" unless $response<success>;
say "response status: $response<status> $response<reason>";

my $text = $response<content>.decode;
say "text size: {$text.chars}";
```

But now we have to convert the HTML code into plain text, *and* the text is too large
to process all at once with LLMs. (Currently LLMs have ≈ 4096 ± 2048 input tokens limits.)

**Remark:** A more completely worked out workflow would have included 
the breaking up of the text into suitably sized chunks, and combining the LLM processed results.

Instead, we are going to ask an LLM to produce artist's bio and discography and then 
we going to pretend we got it from some repository or encyclopedia.

Here we get the text:

```raku
my $text = llm-function(llm-evaluator => llm-configuration('PaLM', max-tokens=> 500))("What is Sinéad O'Connor's bio and discography?")
```
```
# Sinéad O'Connor (born Sinéad Marie Bernadette O'Connor on 8 December 1966) is an Irish singer-songwriter. She rose to fame in the late 1980s with her debut album The Lion and the Cobra (1987), which was followed by I Do Not Want What I Haven't Got (1990), which sold over 10 million copies worldwide. O'Connor's music has been described as "eclectic", and she has been praised for her powerful vocals and her outspoken personality.
# 
# O'Connor has released 10 studio albums, four live albums, and four compilation albums. Her most recent album, I'm Not Bossy, I'm the Boss, was released in 2014. O'Connor has also won two Grammy Awards, two MTV Video Music Awards, and an Ivor Novello Award.
# 
# In addition to her music career, O'Connor has also been involved in activism. She has spoken out about human rights issues, including the rights of women and children, and has campaigned against war and poverty. O'Connor has also been outspoken about her own mental health struggles, and has been a vocal advocate for mental health awareness.
# 
# O'Connor has been married four times and has four children. She currently lives in Dublin, Ireland.
# 
# **Sinéad O'Connor's discography**
# 
# * The Lion and the Cobra (1987)
# * I Do Not Want What I Haven't Got (1990)
# * Am I Not Your Girl? (1992)
# * Universal Mother (1994)
# * Faith and Courage (2000)
# * Sean-Nós Nua (2002)
# * Throw Down Your Arms (2005)
# * Theology (2007)
# * How About I Be Me (And You Be You)? (2012)
# * I'm Not Bossy, I'm the Boss (2014)
```

Here we do Named Entity Recognition (NER) via the LLM function defined above:

```perl6
my $albRes = &fner('album names and years', $text);
```
```
# [```json
# { albums : [ year => 1987 name => The Lion and the Cobra year => 1990 name => I Do Not Want What I Haven't Got year => 1992 name => Am I Not Your Girl? name => Universal Mother year => 1994 year => 2000 name => Faith and Courage year => 2002 name => Sean-Nós Nua name => Throw Down Your Arms year => 2005 year => 2007 name => Theology year => 2012 name => How About I Be Me (And You Be You)? ,
#     { name : "I'm Not Boss]
```

LLMs can produce NER data in several different structures. 
Using the function `deduce-type` from 
["Data::TypeSystem"](https://raku.land/zef:antononcube/Data::TypeSystem), [AAp6],
can help required post-processing:

```perl6
deduce-type($albRes);
```
```
# Vector((Any), 24)
```

Here are a few data type results based in multiple executions of `&fner` 
(more comprehensive study is given in the next section):

```
# Vector((Any), 24)
# Tuple([Atom((Str)), Pair(Atom((Str)), Vector(Struct([name, year], [Str, Int]), 7)), Atom((Str))])
```

Based in our study of the result data type signatures, 
in this workflow we process result of `&fner` with this code:

```perl6
my $albRes2 = $albRes.grep({ $_ ~~ Pair }).rotor(2)>>.Hash; 
if not so $albRes2 { $albRes2 = $albRes.grep(* ~~ Pair).Hash<albums> }

say $albRes2;
```
```
# ({name => The Lion and the Cobra, year => 1987} {name => I Do Not Want What I Haven't Got, year => 1990} {name => Am I Not Your Girl?, year => 1992} {name => Universal Mother, year => 1994} {name => Faith and Courage, year => 2000} {name => Sean-Nós Nua, year => 2002} {name => Throw Down Your Arms, year => 2005} {name => Theology, year => 2007} {name => How About I Be Me (And You Be You)?, year => 2012})
```

Here we tabulate the result:

```perl6
to-pretty-table($albRes2)
```
```
# +------+-------------------------------------+
# | year |                 name                |
# +------+-------------------------------------+
# | 1987 |        The Lion and the Cobra       |
# | 1990 |   I Do Not Want What I Haven't Got  |
# | 1992 |         Am I Not Your Girl?         |
# | 1994 |           Universal Mother          |
# | 2000 |          Faith and Courage          |
# | 2002 |             Sean-Nós Nua            |
# | 2005 |         Throw Down Your Arms        |
# | 2007 |               Theology              |
# | 2012 | How About I Be Me (And You Be You)? |
# +------+-------------------------------------+
```

Here we make a Mermaid-JS timeline plot (after we have figured out the structure of LLM's function output):

```perl6, output.lang=mermaid, output.prompt=NONE
my @timeline = ['timeline', "title Sinéad O'Connor's discography"];
for |$albRes2 -> %record {
    @timeline.append( "{%record<year>} : {%record<name>}");
}
@timeline.join("\n\t");
```
```mermaid
timeline
	title Sinéad O'Connor's discography
	1987 : The Lion and the Cobra
	1990 : I Do Not Want What I Haven't Got
	1992 : Am I Not Your Girl?
	1994 : Universal Mother
	2000 : Faith and Courage
	2002 : Sean-Nós Nua
	2005 : Throw Down Your Arms
	2007 : Theology
	2012 : How About I Be Me (And You Be You)?
```

### Exercise questions

- How the LLM-functions pipeline above should be changed in order to produce timeline plots of different wars?
- How the Raku code should be changed in order to produce timeline plots with Python? (Instead of Mermaid-JS.) 

------

## Statistics of output data types

**Workflow:** We want to see and evaluate the distribution of data types of LLM-function results:
1. Make a pipeline of LLM-functions
2. Create a list of random inputs "expected" by the pipeline
   - Or use the same input multiple times.
3. Deduce the data type of each output
4. Compute descriptive statistics

**Remark:** These kind of statistical workflows can be slow and expensive.
(With the current line-up of LLM services.)

Let us reuse the workflow from the previous section and enhance it with 
data type outputs finding. More precisely we:
1. Generate random music artist names (using an LLM query)
2. Retrieve short biography and discography for each music artist
3. Extract album-and-release-date data for each artist (with NER-by-LLM)
4. Deduce the type for each output, using several different type representations

The data types are investigated with the functions `deduce-type` and `record-types` of 
["Data::TypeSystem"](https://raku.land/zef:antononcube/Data::TypeSystem), [AAp6],
and `tally` and `records-summary` of
["Data::Summarizers"](https://raku.land/zef:antononcube/Data::Summarizers), [AAp7].

Here we define a data retrieval function:

```perl6
my &fdb = llm-function({"What is the short biography and discography of the artist $_?"}, llm-evaluator => llm-configuration('PaLM', max-tokens=> 500));
```
```
# -> **@args, *%args { #`(Block|6266906460480) ... }
```

Here we define (again) the NER function:

```perl6
my &fner = llm-function({"Extract $^a from the text: $^b . Give the result in a JSON format"},                     
                        llm-evaluator => 'PaLM', 
                        form => sub-parser('JSON'))
```
```
# -> **@args, *%args { #`(Block|6266906460912) ... }
```

Here we find 10 random music artists:

```perl6
my @artistNames = |llm-function(llm-evaluator=>'PaLM')("Give 10 random music artist names in a list in JSON format.",
                                  form => sub-parser('JSON'))
```
```
# [```json
# [ image => https://upload.wikimedia.org/wikipedia/commons/thumb/a/a4/Taylor_Swift_2019.jpg/220px-Taylor_Swift_2019.jpg name => Taylor Swift genre => Pop image => https://upload.wikimedia.org/wikipedia/commons/thumb/c/c4/Ed_Sheeran_in_2017.jpg/220px-Ed_Sheeran_in_2017.jpg name => Ed Sheeran genre => Pop genre => Pop name => Adele image => https://upload.wikimedia.org/wikipedia/commons/thumb/c/c2/Adele_at_the_2016_Brit_Awards.jpg/220px-Adele_at_the_2016_Brit_Awards.jpg ,
#   { name Justin Bieber genre Pop image : "https://upload.wikimedia.org/wikipedia/commons/thumb/ 5 59 /Justin_Bieber]
```

Here is a loop that generates the biographies and does NER over them:

```perl6
my @dbRes = do for @artistNames -> $a {
    #say '=' x 6, " $a " , '=' x 6; 
    my $text = &fdb($a);
    #say $text;
    #say '-' x 12;
    my $recs = &fner('album names and release dates', $text);    
    #say $recs;
    $recs
}
```
```
# [[```json albums => [{name => Healing Is Difficult, release_date => 2001} {name => Some People Have Real Problems, release_date => 2004} {name => Colour the Small One, release_date => 2004} {name => We Are Born, release_date => 2010} {name => 1000 Forms of Fear, release_date => 2014} {name => This Is Acting, release_date => 2016} {name => Everyday Is Christmas, release_date => 2017} {name => Music – Songs from and Inspired by the Motion Picture, release_date => 2021}] ```] [```json albums => [{name => Taylor Swift, release_date => 2006} {name => Fearless, release_date => 2008} {name => Speak Now, release_date => 2010} {name => Red, release_date => 2012} {name => 1989, release_date => 2014} {name => Reputation, release_date => 2017} {name => Lover, release_date => 2019}] ```] [```json albums => [{name => Taylor Swift, release_date => 2006} {name => Fearless, release_date => 2008} {name => Speak Now, release_date => 2010} {name => Red, release_date => 2012} {name => 1989, release_date => 2014} {name => Reputation, release_date => 2017}] ```] [```json albums => [{name => Thriller, release_date => 1982} {name => Sgt. Pepper's Lonely Hearts Club Band, release_date => 1967} {name => Like a Virgin, release_date => 1984} {name => 1989, release_date => 2014} {name => 21, release_date => 2011}] ```] [```json albums => [{name => +, release_date => 2011} {name => ×, release_date => 2014} {name => ÷, release_date => 2017} {name => No.6 Collaborations Project, release_date => 2019}] ```] [``` {name => +, release_date => 2011} {name => ×, release_date => 2017} {name => ÷, release_date => 2017} {name => No. 6 Collaborations Project, release_date => 2019} ```] [```json albums => [{name => Taylor Swift, release_date => 2006} {name => Fearless, release_date => 2008} {name => Speak Now, release_date => 2010} {name => Red, release_date => 2012} {name => 1989, release_date => 2014} {name => Reputation, release_date => 2017} {name => Lover, release_date => 2019} {name => Folklore, release_date => 2020} {name => Evermore, release_date => 2020}] ```] [``` albums => [{name => Elvis Presley, release_date => 1956} {name => Please Please Me, release_date => 1963} {name => Thriller, release_date => 1982} {name => Like a Virgin, release_date => 1984} {name => 1989, release_date => 2014}] ```] [```json albums => [{name => 19, release_date => 2008} {name => 21, release_date => 2011} {name => 25, release_date => 2015} {name => 30, release_date => 2021}] ```] [``` albums => [{name => 19, release_date => 2008} {name => 21, release_date => 2011} {name => 25, release_date => 2015} {name => 30, release_date => 2021}] ```] [```
# [ album => The Singles release_date => 1984 release_date => 1986 album => The Remixes release_date => 1990 album => The Greatest Hits release_date => 1991 album => The Remixes II album => The Singles 1984-1993 release_date => 1993 release_date => 1994 album => The Remixes III release_date => 1997 album => The Very Best of album => The Singles 1984-2004 release_date => 2004 album => The Remixes IV release_date => 2005 ,
#   { album The Best of ,] [```json
# { albums : [ name => John Lennon/Plastic Ono Band release_date => 1970 name => Imagine release_date => 1971 release_date => 1973 name => Mind Games release_date => 1974 name => Walls and Bridges name => Rock 'n' Roll release_date => 1975 release_date => 1980 name => Double Fantasy name => Live Peace in Toronto 1969 release_date => 1969 name => The Concert for Bangladesh release_date => 1971 ,
#     { name Live in New York City release_date 1972] [```json
# { albums : [ release_date => 2009-11-23 name => My World name => My World 2.0 release_date => 2010-03-12 name => Under the Mistletoe release_date => 2011-11-01 name => Believe release_date => 2012-06-19 release_date => 2015-11-13 name => Purpose name => Never Say Never: The Remixes release_date => 2011-11-15 release_date => 2013-11-13 name => Journals ,
#     { name My Worlds Acoustic release_date : " 2010 -] [```json albums => [{name => Generations, release_date => 2005} {name => From Paris to Berlin, release_date => 2007} {name => Mystère, release_date => 2009} {name => Pomme, release_date => 2011} {name => L'Amour, release_date => 2013}] ```] [```json
# { albums : [ release_date => 1992 name => Pop release_date => 1994 name => Die Zweite Haut name => Pop 3 release_date => 1996 release_date => 1998 name => Pop 4 name => Pop 5 release_date => 2000 name => Pop 6 release_date => 2002 name => Pop 7 release_date => 2004 name => Pop 8 release_date => 2006 release_date => 2008 name => Pop 9 ,
#     { name : "Pop] [```json
# { Black Sabbath : [ Black Sabbath 1970 ), Paranoid 1970 ), Master of Reality 1971 ), Vol. 4 1972 ), Sabbath Bloody Sabbath 1973 ), Sabotage 1975 ), Technical Ecstasy 1976 ), Never Say Die! 1978 )
#   ], Solo : [ Blizzard of Ozz 1980 ), Diary of a Madman 1981 ), Bark at the Moon 1983 ), The Ultimate Sin 1986 ), No Rest for the Wicked 1988 ), Just Say Ozzy 1990 ), Ozzmosis 1995 ), Down to Earth 2001 ), Under Cover 2005 ), Black Rain 2007 ), Scream 2010 ), Ordinary Man 2020 )
#   ]
# }
# ```] [```json albums => [{name => The Dark Side of the Moon, release_date => 1973-03-01} {name => Wish You Were Here, release_date => 1975-09-15} {name => Animals, release_date => 1977-01-23} {name => The Wall, release_date => 1979-11-30} {name => A Momentary Lapse of Reason, release_date => 1987-09-12} {name => The Division Bell, release_date => 1994-09-28} {name => The Endless River, release_date => 2014-11-10}] ```] [``` 5ive => {5ive => {release_date => 1998-06-08}, 5ive: The Final Chapter => {release_date => 2007-06-25}, Invincible => {release_date => 2001-05-21}, Kingsize => {release_date => 2002-05-13}, The Greatest Hits => {release_date => 2004-10-18}} ```] [```json albums => [{name => 59, release_date => 2015}] ```] [```json albums => [{name => My World (EP), release_date => 2009-11-17} {name => My World 2.0, release_date => 2010-03-12} {name => Under the Mistletoe, release_date => 2011-11-01} {name => Believe, release_date => 2012-06-19} {name => Purpose, release_date => 2015-11-13} {name => Changes, release_date => 2020-02-14}] ```]]
```

Here we call `deduce-type` on each LLM output:

```perl6
.say for @dbRes.map({ deduce-type($_) })
```
```
# Tuple([Atom((Str)), Pair(Atom((Str)), Vector(Assoc(Atom((Str)), Atom((Str)), 2), 8)), Atom((Str))])
# Tuple([Atom((Str)), Pair(Atom((Str)), Vector(Assoc(Atom((Str)), Atom((Str)), 2), 7)), Atom((Str))])
# Tuple([Atom((Str)), Pair(Atom((Str)), Vector(Assoc(Atom((Str)), Atom((Str)), 2), 6)), Atom((Str))])
# Tuple([Atom((Str)), Pair(Atom((Str)), Vector(Assoc(Atom((Str)), Atom((Str)), 2), 5)), Atom((Str))])
# Tuple([Atom((Str)), Pair(Atom((Str)), Vector(Assoc(Atom((Str)), Atom((Str)), 2), 4)), Atom((Str))])
# Tuple([Atom((Str)), Assoc(Atom((Str)), Atom((Str)), 2), Assoc(Atom((Str)), Atom((Str)), 2), Assoc(Atom((Str)), Atom((Str)), 2), Assoc(Atom((Str)), Atom((Str)), 2), Atom((Str))])
# Tuple([Atom((Str)), Pair(Atom((Str)), Vector(Assoc(Atom((Str)), Atom((Str)), 2), 9)), Atom((Str))])
# Tuple([Atom((Str)), Pair(Atom((Str)), Vector(Assoc(Atom((Str)), Atom((Str)), 2), 5)), Atom((Str))])
# Tuple([Atom((Str)), Pair(Atom((Str)), Vector(Assoc(Atom((Str)), Atom((Str)), 2), 4)), Atom((Str))])
# Tuple([Atom((Str)), Pair(Atom((Str)), Vector(Assoc(Atom((Str)), Atom((Str)), 2), 4)), Atom((Str))])
# Vector((Any), 23)
# Vector((Any), 24)
# Vector((Any), 24)
# Tuple([Atom((Str)), Pair(Atom((Str)), Vector(Assoc(Atom((Str)), Atom((Str)), 2), 5)), Atom((Str))])
# Vector((Any), 24)
# Vector((Any), 65)
# Tuple([Atom((Str)), Pair(Atom((Str)), Vector(Assoc(Atom((Str)), Atom((Str)), 2), 7)), Atom((Str))])
# Tuple([Atom((Str)), Pair(Atom((Str)), Assoc(Atom((Str)), Assoc(Atom((Str)), Atom((Str)), 1), 5)), Atom((Str))])
# Tuple([Atom((Str)), Pair(Atom((Str)), Vector(Assoc(Atom((Str)), Atom((Str)), 2), 1)), Atom((Str))])
# Tuple([Atom((Str)), Pair(Atom((Str)), Vector(Assoc(Atom((Str)), Atom((Str)), 2), 6)), Atom((Str))])
```

Here we redo the type deduction using the adverb `:tally`:

```perl6
.say for @dbRes.map({ deduce-type($_):tally })
```
```
# Tuple([Atom((Str)) => 2, Pair(Atom((Str)), Vector(Assoc(Atom((Str)), Atom((Str)), 2), 8)) => 1], 3)
# Tuple([Atom((Str)) => 2, Pair(Atom((Str)), Vector(Assoc(Atom((Str)), Atom((Str)), 2), 7)) => 1], 3)
# Tuple([Atom((Str)) => 2, Pair(Atom((Str)), Vector(Assoc(Atom((Str)), Atom((Str)), 2), 6)) => 1], 3)
# Tuple([Atom((Str)) => 2, Pair(Atom((Str)), Vector(Assoc(Atom((Str)), Atom((Str)), 2), 5)) => 1], 3)
# Tuple([Atom((Str)) => 2, Pair(Atom((Str)), Vector(Assoc(Atom((Str)), Atom((Str)), 2), 4)) => 1], 3)
# Tuple([Assoc(Atom((Str)), Atom((Str)), 2) => 4, Atom((Str)) => 2], 6)
# Tuple([Atom((Str)) => 2, Pair(Atom((Str)), Vector(Assoc(Atom((Str)), Atom((Str)), 2), 9)) => 1], 3)
# Tuple([Atom((Str)) => 2, Pair(Atom((Str)), Vector(Assoc(Atom((Str)), Atom((Str)), 2), 5)) => 1], 3)
# Tuple([Atom((Str)) => 2, Pair(Atom((Str)), Vector(Assoc(Atom((Str)), Atom((Str)), 2), 4)) => 1], 3)
# Tuple([Atom((Str)) => 2, Pair(Atom((Str)), Vector(Assoc(Atom((Str)), Atom((Str)), 2), 4)) => 1], 3)
# Tuple([Atom((Str)) => 5, Pair(Atom((Str)), Atom((Str))) => 18], 23)
# Tuple([Atom((Str)) => 8, Pair(Atom((Str)), Atom((Str))) => 16], 24)
# Tuple([Atom((Int)) => 1, Atom((Str)) => 9, Pair(Atom((Str)), Atom((Str))) => 14], 24)
# Tuple([Atom((Str)) => 2, Pair(Atom((Str)), Vector(Assoc(Atom((Str)), Atom((Str)), 2), 5)) => 1], 3)
# Tuple([Atom((Str)) => 6, Pair(Atom((Str)), Atom((Str))) => 18], 24)
# Tuple([Atom((Int)) => 20, Atom((Str)) => 45], 65)
# Tuple([Atom((Str)) => 2, Pair(Atom((Str)), Vector(Assoc(Atom((Str)), Atom((Str)), 2), 7)) => 1], 3)
# Tuple([Atom((Str)) => 2, Pair(Atom((Str)), Assoc(Atom((Str)), Assoc(Atom((Str)), Atom((Str)), 1), 5)) => 1], 3)
# Tuple([Atom((Str)) => 2, Pair(Atom((Str)), Vector(Assoc(Atom((Str)), Atom((Str)), 2), 1)) => 1], 3)
# Tuple([Atom((Str)) => 2, Pair(Atom((Str)), Vector(Assoc(Atom((Str)), Atom((Str)), 2), 6)) => 1], 3)
```

We see that the LLM outputs produce lists of `Pair` objects "surrounded" by strings:

```perl6
.say for @dbRes.map({record-types($_)})
```
```
# ((Str) (Pair) (Str))
# ((Str) (Pair) (Str))
# ((Str) (Pair) (Str))
# ((Str) (Pair) (Str))
# ((Str) (Pair) (Str))
# ((Str) (Pair) (Pair) (Pair) (Pair) (Str))
# ((Str) (Pair) (Str))
# ((Str) (Pair) (Str))
# ((Str) (Pair) (Str))
# ((Str) (Pair) (Str))
# ((Str) (Pair) (Pair) (Pair) (Pair) (Pair) (Pair) (Pair) (Pair) (Pair) (Pair) (Pair) (Pair) (Pair) (Pair) (Pair) (Pair) (Pair) (Pair) (Str) (Str) (Str) (Str))
# ((Str) (Str) (Str) (Pair) (Pair) (Pair) (Pair) (Pair) (Pair) (Pair) (Pair) (Pair) (Pair) (Pair) (Pair) (Pair) (Pair) (Pair) (Pair