read-only demo

Videos 3ySF0I5iE_0

A Practitioner's Guide to Graphs - Tim Ainge, Good Collective

index_state ready data_status ok

AI Engineer· published 2026-07-18· 0:14:17· en-US· indexed 2026-08-10 19:43

Open on YouTube

Scene timeline

  1. Shot 0, 0:00 to 0:13, 1 of 1 keyframes kept
  2. Shot 1, 0:13 to 0:44, 1 of 1 keyframes kept
  3. Shot 2, 0:44 to 1:15, 1 of 1 keyframes kept
  4. Shot 3, 1:15 to 1:46, 0 of 1 keyframes kept
  5. Shot 4, 1:46 to 1:59, 1 of 1 keyframes kept
  6. Shot 5, 1:59 to 2:13, 1 of 1 keyframes kept
  7. Shot 6, 2:13 to 2:42, 1 of 1 keyframes kept
  8. Shot 7, 2:42 to 3:11, 1 of 1 keyframes kept
  9. Shot 8, 3:11 to 3:40, 0 of 1 keyframes kept
  10. Shot 9, 3:40 to 4:18, 1 of 1 keyframes kept
  11. Shot 10, 4:18 to 4:34, 1 of 1 keyframes kept
  12. Shot 11, 4:34 to 5:23, 1 of 1 keyframes kept
  13. Shot 12, 5:23 to 6:12, 1 of 1 keyframes kept
  14. Shot 13, 6:12 to 6:36, 1 of 1 keyframes kept
  15. Shot 14, 6:36 to 7:07, 1 of 1 keyframes kept
  16. Shot 15, 7:07 to 7:38, 1 of 1 keyframes kept
  17. Shot 16, 7:38 to 8:05, 1 of 1 keyframes kept
  18. Shot 17, 8:05 to 8:32, 1 of 1 keyframes kept
  19. Shot 18, 8:32 to 9:00, 0 of 1 keyframes kept
  20. Shot 19, 9:00 to 9:08, 1 of 1 keyframes kept
  21. Shot 20, 9:08 to 9:14, 1 of 1 keyframes kept
  22. Shot 21, 9:14 to 9:45, 1 of 1 keyframes kept
  23. Shot 22, 9:45 to 10:13, 1 of 1 keyframes kept
  24. Shot 23, 10:13 to 10:40, 1 of 1 keyframes kept
  25. Shot 24, 10:40 to 11:08, 0 of 1 keyframes kept
  26. Shot 25, 11:08 to 11:35, 1 of 1 keyframes kept
  27. Shot 26, 11:35 to 12:02, 1 of 1 keyframes kept
  28. Shot 27, 12:02 to 12:29, 0 of 1 keyframes kept
  29. Shot 28, 12:29 to 12:56, 0 of 1 keyframes kept
  30. Shot 29, 12:56 to 13:46, 1 of 1 keyframes kept
  31. Shot 30, 13:46 to 14:17, 1 of 1 keyframes kept

31 shot(s).

keyframes kept every frame deduplicated

What was stored

cues
111
whisperx 111
chunks
26
from 111 cues
keyframes
25
kept of 31 captured
frames with text
25
418 lines read
chapters
0
from the source metadata
keyframe bytes
1.9 MB
word timings on 111 cues

Provenance

Each pipeline stage, its state and the model that produced it
stage state model started took
fetch done 2026-08-09 23:59 1m 17s
stt done 2026-08-10 00:01 14s
chunk done 2026-08-10 00:01 0s
text_embed done 2026-08-10 19:43 0s
keyframe done 2026-08-10 00:01 39s
ocr done 2026-08-10 00:02 12s
frame_embed done 2026-08-10 19:43 5s

Frames, and what the machine read

  • 0:10 #0 done6 line(s)

    shot 0·sharpness 319.8

    1. AlEngineer0.96
    2. World'sFair1.00
    3. A Practitioner's Guide to Graphs1.00
    4. How to make you Al applications smarter, cheaper, and more reliable0.99
    5. GoodCollective1.00
    6. CapabilityxStrategy=Delivery1.00
  • 0:40 #1 done3 line(s)

    shot 1·sharpness 795.6

    1. If I have a hammer, is everything a graph?1.00
    2. Obsidian knowledge graph1.00
    3. GraphRA60.95
  • 1:11 #2 done6 line(s)

    shot 2·sharpness 899.9

    1. If I have a hammer, is everything a graph?1.00
    2. graphs from1.00
    3. 1st principles1.00
    4. Obsidian knowledge graph1.00
    5. A0.52
    6. GraphRA60.94
  • 1:21 #3 skipped

    shot 3·duplicate of #2

  • 1:56 #4 done10 line(s)

    shot 4·sharpness 520.3

    1. The structure of things to come1.00
    2. The talk1.00
    3. PART1.00
    4. Personalised PageRank1.00
    5. COVERS1.00
    6. Graph algorithms0.99
    7. COVERS1.00
    8. Shortest path0.99
    9. COVERS1.00
    10. Subgraph matching1.00
  • 2:01 #5 done4 line(s)

    shot 5·sharpness 317.8

    1. The structure of things to come0.99
    2. Principle1.00
    3. Code1.00
    4. Examples1.00
  • 2:22 #6 done14 line(s)

    shot 6·sharpness 274.8

    1. What is a graph1.00
    2. Nodes, edges, weights, properties.1.00
    3. Milk0.97
    4. CONTAINS1.00
    5. Whisk together1.00
    6. HAS_STEP1.00
    7. Pancakes1.00
    8. CONTAINS1.00
    9. CONTAINS1.00
    10. Recipe1.00
    11. Egg1.00
    12. Ingredient1.00
    13. Flour1.00
    14. Step1.00
  • 2:51 #7 done37 line(s)

    shot 7·sharpness 661.7

    1. Extract a basic graph0.99
    2. Principle: unstructured data isn't much more helpful than unstructured text.1.00
    3. from pydantic import BaseModel1.00
    4. 4 people serves0.99
    5. from pydantic_ai import Agent1.00
    6. pancake recipe0.99
    7. requires1.00
    8. class Triple(BaseModel):1.00
    9. needs1.00
    10. subject: str0.97
    11. predicate: str1.00
    12. plain fid@pbined with0.88
    13. object: str1.00
    14. Milk1.00
    15. contains1.00
    16. # no schema, no vocabulary, no entity resolution0.99
    17. breakfast1.00
    18. agent = Agent(0.98
    19. is a0.92
    20. "anthropic:claude-sonnet-4-6",1.00
    21. Pancakes1.00
    22. has ingredient1.00
    23. output_type=list[Triple],1.00
    24. eggs1.00
    25. system_prompt=(1.00
    26. needs1.00
    27. "Pull the key facts out as (subject, predicate,1.00
    28. "object) triples. Use whatever vocab fits, yolo."1.00
    29. ),0.94
    30. Flour1.00
    31. made withixed with0.99
    32. triples = agent.run_sync(recipe_text).output0.99
    33. cooked on0.97
    34. uses1.00
    35. the batter0.95
    36. Egg1.00
    37. a pan0.99
  • 3:23 #8 skipped

    shot 8·duplicate of #7

  • 4:13 #9 done24 line(s)

    shot 9·sharpness 700.6

    1. Defining the schema (the shape)1.00
    2. Principle: give the extractor a shape - a schema - to fill. A shape gets you structure.0.98
    3. from pydantic import BaseModel, Field0.98
    4. from pydantic_ai import Agent1.00
    5. garlic1.00
    6. class Ingredient(BaseModel):1.00
    7. name: str1.00
    8. quantity: float | None = None0.99
    9. unit: str |0.97
    10. None = None0.99
    11. # 'cup', 'g', 'tbsp'0.97
    12. parsley1.00
    13. parmesan1.00
    14. class Recipe(BaseModel):0.99
    15. title: str0.97
    16. ingredients: list[Ingredient]0.99
    17. Garlic Butter Pasta1.00
    18. CONTAINS1.00
    19. # the schema IS the contract - no free-form vocab0.99
    20. ...0.94
    21. agent = Agent("anthropic:claude-sonnet-4-6", output_type=Recipe)0.99
    22. recipe = agent.run_sync(recipe_text).output1.00
    23. spaghetti1.00
    24. butter1.00
  • 4:30 #10 done40 line(s)

    shot 10·sharpness 1022.4

    1. A recipe is more than its ingredients0.98
    2. The shape grows with the domain - add steps , and the technique each one applies.0.98
    3. toss1.00
    4. class Ingredient(BaseModel):1.00
    5. name: str0.98
    6. TECHNIQUE1.00
    7. quantity: float | None = Field(None, description="...")0.97
    8. unit: str |0.95
    9. None = Field(None, description="... ")0.96
    10. Toss the pasta in tese's0.87
    11. parsley1.00
    12. class Step(BaseModel):1.00
    13. HAS_STEP1.00
    14. text: str1.00
    15. parmesan1.00
    16. CONTAINS1.00
    17. technique: str | None = Field(None, description="... ")0.97
    18. spaghetti1.00
    19. CONTAINS1.00
    20. CONTAINS1.00
    21. uses: list[str] = Field(default_factory=list, description=".0.99
    22. CONTAINS1.00
    23. garlic1.00
    24. USES1.00
    25. HAS_STEP1.00
    26. Garlic Butter Pasta1.00
    27. HAS_STEP0.99
    28. CONTAINS0.99
    29. class Recipe(BaseModel):1.00
    30. title: str0.99
    31. TECHNIQUE0.99
    32. Boil the spaghetti un...0.99
    33. Melt the butter, then...0.95
    34. steps: list[Step]0.99
    35. ingredients: list[Ingredient]0.99
    36. boil0.95
    37. butter0.98
    38. TECHNIQUE1.00
    39. saute1.00
    40. + Techniques - the verb each step applies (saute, boil, toss)0.98
  • 4:44 #11 done42 line(s)

    shot 11·sharpness 1132.6

    1. Adding ontology in the prompt0.99
    2. Principle: a schema provides shape, the ontology describes what should go into it.0.99
    3. Oyster Sauce0.99
    4. Salt1.00
    5. # the ontology, expressed as rules in the system prompt0.99
    6. Oil1.00
    7. Minced Garlic1.00
    8. SYSTEM_PROMPT = (0.98
    9. Bean Sprouts0.98
    10. 1 tbs pinch0.97
    11. "Extract recipes into STRICT, schema-conformant form:\n"0.99
    12. 5 tbs0.99
    13. 1 tsp0.97
    14. Egg1.00
    15. "1. CANONICAL UNITS - convert to SI:\n"0.99
    16. 1 cup0.96
    17. mass → grams ('g'); volume → millilitres ('ml')\n"0.99
    18. Sesame Seed Oil1.00
    19. 2 tsp0.99
    20. 0.51.00
    21. (1 cup → 240 ml; 1 tbsp → 15 ml; 1 oz → 28 g)\n"0.97
    22. Mushrooms1.00
    23. countable items (eggs, cloves) keep a null unit.\n"1.00
    24. CANONICAL NAMES - clean, lowercase, singular:\n"0.99
    25. 0.25 lb0.97
    26. 'plain flour' / 'all-purpose' → 'flour'\n"0.98
    27. Soy Sauce1.00
    28. 0.5 cup1.00
    29. Beef Lo Mein1.00
    30. Noodles1.00
    31. strip brands & loose adjectives ('chopped', 'fresh'),\n"1.00
    32. 0.5 lb0.93
    33. keep distinguishing words ('smoked', 'self-raising').\n"1.00
    34. "Conform to the schema; don't invent ingredients."1.00
    35. Onion1.00
    36. 3 tbs1.00
    37. Sugar1.00
    38. Beef1.00
    39. Pepper1.00
    40. Water1.00
    41. Ginger1.00
    42. Starch1.00
  • 6:02 #12 done30 line(s)

    shot 12·sharpness 900.5

    1. Simple entity matching1.00
    2. Principle: epic power-up = resolve your entities.0.99
    3. CONTAINS0.98
    4. soy sauce0.99
    5. Beef Lo Mein0.99
    6. # a synonym / index table maps surface forms → one canonical nod0.99
    7. INGREDIENTS = {0.97
    8. CONTAINS1.00
    9. CONTAINSCONTAINS0.99
    10. "garlic": ["garlic clove", "minced garlic", "2 cloves garlic"1.00
    11. CONTAINS1.00
    12. water1.00
    13. "shallot": ["challots", "eschalot", "golden shallot"],0.99
    14. Teriyaki Chicken CasS.CONTANS0.95
    15. concaunSpiced Fish Tac...0.81
    16. 10.65
    17. garlic1.00
    18. def normalise(name: str) → str:0.98
    19. onion1.00
    20. cleaned = clean(name)0.99
    21. # lowercase, str0.97
    22. CONT1.00
    23. CONTANS0.94
    24. EONTAINSCONTAINS0.96
    25. return SYN_TO_CANON.get(cleaned, cleaned)0.99
    26. # exact hit → ca0.94
    27. Egyptian Fatteh0.98
    28. Chicken Handi0.99
    29. CONTAINS1.00
    30. cumin1.00
  • 6:22 #13 done20 line(s)

    shot 13·sharpness 647.5

    1. Better entity matching1.00
    2. Principle: Hybrid approaches often yield the best results. In this case semantic entity matching.1.00
    3. # hybrid match = semantic vector score + lexical score0.98
    4. def hybrid_lookup(query, candidates):0.99
    5. q, *cands = embed([query, *candidates])0.99
    6. # all-MiniLM-L6-v20.99
    7. coriander1.00
    8. capsicurhilli1.00
    9. scores = []0.99
    10. apoing onion0.96
    11. for cand, vec in zip(candidates, cands):0.99
    12. flour0.98
    13. vector = (cosine(q, vec) + 1) / 20.97
    14. # semantic kinship1.00
    15. lexical = token_sort_ratio(query, cand) / 100 # surface overlap0.99
    16. milk1.00
    17. sugar1.00
    18. scores.append(0.6 * vector + 0.4 * lexical)0.99
    19. return best_first(candidates, scores)1.00
    20. hybrid_lookup("garbanzo", existing_nodes) # → 'chickpea'0.97
  • 6:43 #14 done15 line(s)

    shot 14·sharpness 412.0

    1. Graph queries1.00
    2. Principle: query by relationship, not just by node – and get a subgraph back.0.99
    3. // graph - walk the relationship0.95
    4. MATCH (r:Recipe)-[:CONTAINS]→(i:Ingredient)0.99
    5. WHERE i.name = 'garlic'0.97
    6. RETURN r,i0.99
    7. -- relational - join through the link table0.99
    8. garlic?1.00
    9. SELECT r.title1.00
    10. FROM recipes r0.99
    11. JOIN recipe_ingredients ri ON ri.recipe_id = r.id1.00
    12. JOIN ingredients0.98
    13. i ON i.id = ri.ingredient_id1.00
    14. WHERE i.name = 'garlic';1.00
    15. garlic?– the question, as a seed node0.98
  • 7:22 #15 done34 line(s)

    shot 15·sharpness 795.2

    1. Graph queries1.00
    2. Principle: query by relationship, not just by node – and get a subgraph back.0.99
    3. cannellini beans0.99
    4. CONTAINS1.00
    5. // graph - walk the relationship0.97
    6. MATCH (r:Recipe)-[:CONTAINS]→(i:Ingredient)0.99
    7. Croatian Bean Stew0.99
    8. WHERE i.name = 'garlic'0.98
    9. CONTAINS0.98
    10. CONTAINS1.00
    11. RETURN r, i0.96
    12. beef0.96
    13. CONTAINS0.99
    14. Egyptian Fatteh1.00
    15. CONTAINS1.00
    16. -- relational - join through the link table0.99
    17. CONTAINS0.95
    18. garlic?1.00
    19. CONTAINS1.00
    20. SELECT r.title1.00
    21. FROM recipes r0.99
    22. Beef Lo Mein1.00
    23. CONTAINS1.00
    24. Chicken Handi1.00
    25. CONTAINS1.00
    26. onion1.00
    27. JOIN recipe_ingredients ri ON ri.recipe_id = r.id0.99
    28. JOIN ingredients0.99
    29. i ON i.id = ri.ingredient_id0.98
    30. WHERE i.name = 'garlic';1.00
    31. Cajun Spiced Fish Tac...1.00
    32. CONTAINS0.97
    33. white fish1.00
    34. → + their other ingredients - the subgraph you'd hand a model0.97
  • 7:41 #16 done4 line(s)

    shot 16·sharpness 267.4

    1. Personalised PageRank0.99
    2. Plainly: pick one node, wander the edges, keep resetting to where you started. Where you land most often is0.99
    3. what's relevant.0.98
    4. ChickenHandi1.00
  • 8:21 #17 done4 line(s)

    shot 17·sharpness 288.1

    1. Personalised PageRank1.00
    2. Plainly: pick one node, wander the edges, keep resetting to where you started. Where you land most often is0.99
    3. what's relevant.0.99
    4. Egyptian Fatteh0.96
  • 8:41 #18 skipped

    shot 18·duplicate of #17

  • 9:01 #19 done5 line(s)

    shot 19·sharpness 306.2

    1. Personalised PageRank1.00
    2. Principle: The most value comes from being able to highlight related nodes when they aren't obvious.1.00
    3. ginger0.99
    4. garlic1.00
    5. Add the onions and0.98
  • 9:13 #20 done2 line(s)

    shot 20·sharpness 262.9

    1. Personalised PageRank0.99
    2. Principle: The most value comes from being able to highlight related nodes when they aren't obvious.1.00
  • 9:32 #21 done26 line(s)

    shot 21·sharpness 1018.9

    1. PPR in the wild – landmark law0.97
    2. Real-world: seed a walk at one routine case; out of 27,885, the landmark it stands on surfaces.1.00
    3. Johnsonv.Zerbst1.00
    4. Malloy v.Hogan0.97
    5. cites1.00
    6. cites1.00
    7. Buchananv.Kentucky0.98
    8. Powell v Texas0.89
    9. Powell v.Alabama0.98
    10. cites1.00
    11. Estellev.Smith1.00
    12. cites1.00
    13. cites1.00
    14. cites1.00
    15. cites1.00
    16. cites1.00
    17. Kansas v. Cheever0.96
    18. cites1.00
    19. Massiahv.UnitedStates1.00
    20. Fitzpatrickv.UnitedStates1.00
    21. UnitedStatesv.Wade1.00
    22. cites1.00
    23. cites1.00
    24. Kansasv.Marsh0.99
    25. Brownv.UnitedStates1.00
    26. one hop further – into the precedent cluster0.97
  • 10:07 #22 done22 line(s)

    shot 22·sharpness 501.3

    1. Shortest path1.00
    2. Principle: "how does A relate to B, and through what?"0.98
    3. # the path IS the explanation - one NetworkX call1.00
    4. path = nx.shortest_path(0.99
    5. code_graph,1.00
    6. # the eShop "calls" graph0.99
    7. source="CheckoutModel.OnPost",1.00
    8. # the symptom1.00
    9. target="Basket..ctor",1.00
    10. # the constructor we touched0.99
    11. BasketViewModelServic1.00
    12. → CheckoutModel.OnPost1.00
    13. CheckoutModel.SetBask..1.00
    14. #1.00
    15. CheckoutModel.SetBasketModelAsync1.00
    16. CheckoutModel.OnPost1.00
    17. BasketViewModelService.GetOrCreateBasketForUser1.00
    18. #1.00
    19. BasketViewModelService.CreateBasketForUser1.00
    20. #1.00
    21. Basket..ctor1.00
    22. the path is the explanation - a 4-hop calls chain from checkout down to the constructor0.99
  • 10:32 #23 done25 line(s)

    shot 23·sharpness 566.1

    1. Shortest path1.00
    2. Principle: "how does A relate to B, and through what?"0.99
    3. # the path IS the explanation - one NetworkX call0.99
    4. path = nx.shortest_path(1.00
    5. code_graph,1.00
    6. # the eShop "calls" graph0.98
    7. source="CheckoutModel.OnPost",1.00
    8. # the symptom1.00
    9. target="Basket..ctor",1.00
    10. # the constructor we touched0.99
    11. BasketViewModelServic1.00
    12. → CheckoutModel.OnPost0.99
    13. CheckoutModel.SetBask..1.00
    14. #1.00
    15. #1.00
    16. → BasketViewModelService.GetOrCreateBasketForUser0.99
    17. CheckoutModel.SetBasketModelAsync1.00
    18. .ctor1.00
    19. BasketViewModelServic...0.96
    20. CheckoutModel.OnPost1.00
    21. #1.00
    22. BasketViewModelService.CreateBasketForUser0.99
    23. #1.00
    24. Basket..ctor0.98
    25. the path is the explanation - a 4-hop calls chain from checkout down to the constructor0.99

Transcript

111 cues· 2,277 words· 12,769 chars

  1. 0:01 Hi, I'm Tim Ainge from Liquid Collective, and welcome to AI Engineer's Presentation, A Practitioner's Guide to Graphs.
  2. 0:08 How to make your AI applications smarter, cheaper, and more reliable.
  3. 0:14 Graphs have always been a powerful foundation of computer science, and they look beautiful,
  4. 0:19 Sometimes they're genuinely not the right tool for the job.
  5. 0:23 We've all felt the wonder of a mesmerising data science graph, or ogled the graph view of our obsidian vault.
  6. 0:31 It can be tempting to rush into something like GraphRack or rebuilding our e-commerce shop with a graph database, but often we don't see the instant payoff we might have expected.
  7. 0:42 In frustration, many journeys end here, in the dust, at the bottom of the valley of despair and disillusionment.
  8. 0:50 What's on the other side of the valley and how do we get there?
  9. 0:53 That's exactly the question that sparked the idea for this talk.
  10. 0:56 Have I nailed all of the answers?
  11. 0:58 Definitely not.
  12. 1:00 But what I'm finding is that the more I learn about the fundamentals of graph data structures and algorithms, the more interesting opportunities seem to present themselves.
  13. 1:09 Many of these graph-native use cases, or good fits for graphs, are also a lovely complement to many of the search, pattern recognition, retrieval, or knowledge-based problems that are ripe for solving in the AI age.
  14. 1:23 Now just a quick disclaimer, this talk isn't going to go into graph rag or agent memory graphs.
  15. 1:29 Not because I'm throwing shade on those patterns and products, but partly because there'll be many other talks covering each of those single topics.
  16. 1:37 But more importantly, this talk is for AI builders, and I'd like to focus on the underlying patterns, which may just help you come up with your next big graph-powered AI application.
  17. 1:47 Today we're going to speedrun the basics of graphs, then we'll walk through some tips and tricks for building better graphs to get better results, and then we'll look at graph-native algorithms that leverage a graph and the benefits that they deliver.
  18. 2:01 At each step of the way, we'll open with a principle, look at an easy example and some code, and then finally we'll reference some real-world examples with real-world benefits
  19. 2:14 all right let's speed on the basics what's a graph a graph is something that has nodes also called vertices and edges which i sometimes call relationships that connect the nodes together that's it that is the most basic definition of a graph we can have different types of nodes and edges which convey more meaning and we can also put labels on edges and nodes and have properties and of course edges can have direction
  20. 2:44 Now that we've speed around that, a really, really important part of getting good value out of graphs is how we build good graphs.
  21. 2:53 Today, we're going to focus on extracting graphs from unstructured text, because that's a pretty common use case and a pretty popular one at the moment.
  22. 3:01 So in this example, we've defined a very basic data structure for our graph.
  23. 3:06 a triple that has a subject, a predicate, and an object, or a node that somehow relates to another node.
  24. 3:16 And we say to our agent, hey, go and pull the key information out of this thing as subject, predicate, and object triples.
  25. 3:25 You figure it out.
  26. 3:28 And then we give it a pancake recipe.
  27. 3:31 It's done an all right job.
  28. 3:32 We've got a graph.
  29. 3:36 We wouldn't get very far with this graph.
  30. 3:37 It's got some problems and we'll talk through that next.
  31. 3:42 One of the key principles about building better graphs is giving the extractor a schema to fill.
  32. 3:48 In this case, if we say instead of using triples, use a recipe and a recipe has ingredients and ingredients have a quantity.
  33. 3:57 If we give this to an agent with structured outputs, what we get back is instantly way more meaningful than the graph we had before and a lot tidier.
  34. 4:10 So the benefit here is that with consistent node and edge times, relationships become meaningful and something that we can interrogate or query.
  35. 4:19 Let's take this a little bit further to say that a recipe has ingredients, but it also has steps, and each step is the application of a cooking technique.
  36. 4:30 Now we've got a graph with structure that's starting to look a bit interesting.
  37. 4:34 Now that we have a well-defined schema and a nicely structured graph,
  38. 4:38 We need to add detail to our ontology.
  39. 4:43 The ontology describes how to extract information into our graph or precisely what to put into that structure.
  40. 4:50 In our case, we want to provide instructions to our agent to standardize the formatting of ingredient names and to standardize units on the metric system to make matching and conversion easier.
  41. 5:04 These extra instructions are just as important to the TADA model as the schema is.
  42. 5:09 And boom, there we go.
  43. 5:11 We've got lowercase ingredients and metric units.
  44. 5:16 We know that the best prompt in the world isn't bulletproof, though, so we'll look next how to make sure we really do standardize our units.
  45. 5:24 Here's an example where we have a couple of ingredients that probably shouldn't be represented by multiple nodes.
  46. 5:30 We've got garlic cloves and minced garlic.
  47. 5:33 cumin and cumin seeds, vegetable oil and oil.
  48. 5:38 We've also got plain old garlic down there as well.
  49. 5:43 So in our first attempt at solving the potato-potato problem, we can see that by taking a naive approach to mapping these, we can eliminate the duplication, which unifies the nodes, but it also strengthens the relationships between the different recipes that have common ingredient.
  50. 5:59 We'll explain why this is helpful later.

Open at this second