<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Vanya Mittal</title>
    <description>The latest articles on DEV Community by Vanya Mittal (@vanya_mittal_009fd2d47161).</description>
    <link>https://dev.to/vanya_mittal_009fd2d47161</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4191944%2F735a680d-1cc9-4bd2-9986-17f49e503879.png</url>
      <title>DEV Community: Vanya Mittal</title>
      <link>https://dev.to/vanya_mittal_009fd2d47161</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/vanya_mittal_009fd2d47161"/>
    <language>en</language>
    <item>
      <title>PedigreeGraph: Built an AI agent that reads a family tree</title>
      <dc:creator>Vanya Mittal</dc:creator>
      <pubDate>Sun, 18 Oct 2026 15:15:10 +0000</pubDate>
      <link>https://dev.to/vanya_mittal_009fd2d47161/pedigreegraph-built-an-ai-agent-that-reads-a-family-tree-kim</link>
      <guid>https://dev.to/vanya_mittal_009fd2d47161/pedigreegraph-built-an-ai-agent-that-reads-a-family-tree-kim</guid>
      <description>&lt;p&gt;&lt;strong&gt;Built for Graph Hacks: Context for AI Agents (FalkorDB x WeMakeDevs), Track 01: Agents That Act on Connected Data.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The story nobody told
&lt;/h2&gt;

&lt;p&gt;Most of us know our families through stories: who laughed the loudest, who cooked the best, who we lost too soon. But some stories are never told, because nobody knew they were there.&lt;/p&gt;

&lt;p&gt;Beta-thalassemia is one of them. One ICMR estimate puts the number of carriers in India at 35 to 45 million, based on a carrier rate of roughly 3.5 to 4 per cent (&lt;a href="https://www.ncbi.nlm.nih.gov/pmc/articles/PMC4042365/" rel="noopener noreferrer"&gt;source&lt;/a&gt;). Other sources give slightly different figures, so read it as a rough scale. The hard part is that carriers usually have no symptoms, so they have no reason to suspect anything. When both partners are carriers, each pregnancy has a 25 per cent chance of a child born with thalassemia major (&lt;a href="https://www.thestatesman.com/supplements/science_supplements/thalassemia-is-a-silent-genetic-disorder-that-can-be-prevented-through-awareness-and-screening-1503432889.html" rel="noopener noreferrer"&gt;source&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Nobody in that story did anything wrong. They just didn't know.&lt;/p&gt;

&lt;p&gt;That made me think: the warning signs are often already in the family, in who is related to whom, who is affected, and who shares ancestors. That is a graph.&lt;/p&gt;

&lt;p&gt;My demo video: &lt;a href="https://youtu.be/-cMjirH7sjw" rel="noopener noreferrer"&gt;https://youtu.be/-cMjirH7sjw&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I built
&lt;/h2&gt;

&lt;p&gt;PedigreeGraph stores &lt;strong&gt;30 synthetic families (540 people)&lt;/strong&gt; in FalkorDB. An AI agent, running on Gemini, answers questions like "What is the risk picture for FAM1_P14?" or "Who should be tested first in FAM3?" by calling graph tools. Every answer shows the family path behind it, highlighted on a drawn pedigree. Clicking any person gives an instant report with no AI call at all.&lt;/p&gt;

&lt;p&gt;All data is synthetic. The condition names are real (beta-thalassemia, cystic fibrosis, sickle cell disease, Tay-Sachs disease, familial hypercholesterolemia), but only the inheritance pattern is modelled. This is family-history risk awareness, not a diagnosis.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Try it:&lt;/strong&gt; &lt;a href="https://pedigreegraph.onrender.com/" rel="noopener noreferrer"&gt;https://pedigreegraph.onrender.com/&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Try your own family:&lt;/strong&gt; &lt;a href="https://pedigreegraph.onrender.com/custom" rel="noopener noreferrer"&gt;https://pedigreegraph.onrender.com/custom&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  The graph model
&lt;/h2&gt;

&lt;p&gt;It is deliberately small:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cypher"&gt;&lt;code&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;:Person&lt;/span&gt; &lt;span class="ss"&gt;{&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt; &lt;span class="n"&gt;family&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt; &lt;span class="n"&gt;condition&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sex&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt; &lt;span class="n"&gt;generation&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt; &lt;span class="n"&gt;affected&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tested&lt;/span&gt;&lt;span class="ss"&gt;})&lt;/span&gt;
&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;:Person&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="ss"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;:PARENT_OF&lt;/span&gt;&lt;span class="ss"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;:Person&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;
&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;:Person&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="ss"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;:PARTNER_OF&lt;/span&gt;&lt;span class="ss"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;:Person&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is 540 people, 780 &lt;code&gt;PARENT_OF&lt;/code&gt; edges and 150 &lt;code&gt;PARTNER_OF&lt;/code&gt; edges. The graph only stores what a genetic counselor could observe. The true genotypes and the inheritance mode live outside it, so the agent can't cheat.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the graph does the work
&lt;/h2&gt;

&lt;p&gt;The questions that matter are about relationships, and they are multi-hop Cypher queries.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Obligate carriers.&lt;/strong&gt; An unaffected parent of an affected child must carry a recessive allele:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cypher"&gt;&lt;code&gt;&lt;span class="k"&gt;MATCH&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="py"&gt;par:&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt; &lt;span class="ss"&gt;{&lt;/span&gt;&lt;span class="py"&gt;family:&lt;/span&gt;&lt;span class="n"&gt;$fam&lt;/span&gt;&lt;span class="ss"&gt;})&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="ss"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;:PARENT_OF&lt;/span&gt;&lt;span class="ss"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="py"&gt;c:&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt; &lt;span class="ss"&gt;{&lt;/span&gt;&lt;span class="py"&gt;family:&lt;/span&gt;&lt;span class="n"&gt;$fam&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt; &lt;span class="py"&gt;affected:&lt;/span&gt;&lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="ss"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="ow"&gt;NOT&lt;/span&gt; &lt;span class="n"&gt;par.affected&lt;/span&gt;
&lt;span class="k"&gt;RETURN&lt;/span&gt; &lt;span class="n"&gt;par.id&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;collect&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c.id&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Shared ancestors.&lt;/strong&gt; Two partners are related if they descend from the same person. Two variable-length patterns meet at the same ancestor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cypher"&gt;&lt;code&gt;&lt;span class="k"&gt;MATCH&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="py"&gt;a:&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt; &lt;span class="ss"&gt;{&lt;/span&gt;&lt;span class="py"&gt;family:&lt;/span&gt;&lt;span class="n"&gt;$fam&lt;/span&gt;&lt;span class="ss"&gt;})&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="ss"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;:PARTNER_OF&lt;/span&gt;&lt;span class="ss"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="py"&gt;b:&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt; &lt;span class="ss"&gt;{&lt;/span&gt;&lt;span class="py"&gt;family:&lt;/span&gt;&lt;span class="n"&gt;$fam&lt;/span&gt;&lt;span class="ss"&gt;}),&lt;/span&gt;
      &lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="py"&gt;anc:&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="ss"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;:PARENT_OF&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="ss"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="ss"&gt;),&lt;/span&gt;
      &lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="n"&gt;anc&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="ss"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;:PARENT_OF&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="ss"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;RETURN&lt;/span&gt; &lt;span class="n"&gt;a.id&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b.id&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;collect&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="k"&gt;DISTINCT&lt;/span&gt; &lt;span class="n"&gt;anc.id&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The shortest family path&lt;/strong&gt; from a person to the nearest affected relative. This becomes the red line on the tree:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cypher"&gt;&lt;code&gt;&lt;span class="k"&gt;MATCH&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="py"&gt;a:&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt; &lt;span class="ss"&gt;{&lt;/span&gt;&lt;span class="py"&gt;id:&lt;/span&gt;&lt;span class="n"&gt;$id&lt;/span&gt;&lt;span class="ss"&gt;})&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="ss"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;:PARENT_OF&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="m"&gt;6&lt;/span&gt;&lt;span class="ss"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="py"&gt;b:&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt; &lt;span class="ss"&gt;{&lt;/span&gt;&lt;span class="py"&gt;family:&lt;/span&gt;&lt;span class="n"&gt;$fam&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt; &lt;span class="py"&gt;affected:&lt;/span&gt;&lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="ss"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;b.id&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;$id&lt;/span&gt;
&lt;span class="k"&gt;RETURN&lt;/span&gt; &lt;span class="ss"&gt;[&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="ow"&gt;IN&lt;/span&gt; &lt;span class="nf"&gt;nodes&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;n.id&lt;/span&gt;&lt;span class="ss"&gt;]&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;length&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;hops&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;hops&lt;/span&gt; &lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are also queries for each person's affected relatives, from siblings and grandparents to aunts, uncles, nieces and nephews.&lt;/p&gt;

&lt;p&gt;In the demo family FAM1, two cousins (FAM1_P10 and FAM1_P14) are partners and already have an affected child. The graph finds their shared grandparents on its own, and the exact genetics gives a 25 percent chance for each future child.&lt;/p&gt;

&lt;h2&gt;
  
  
  The AI never does the maths
&lt;/h2&gt;

&lt;p&gt;The language model never calculates risk. It chooses tools and explains the results. The probabilities come from deterministic code that uses exact variable elimination on the pedigree, so a shared ancestor is counted correctly.&lt;/p&gt;

&lt;p&gt;One honest limitation: that calculation runs in Python over the family structure read from FalkorDB, not inside the database.&lt;/p&gt;

&lt;p&gt;To check the graph side, I wrote &lt;code&gt;test_cypher.py&lt;/code&gt;. It compares every Cypher query with an independent pure-Python implementation for every person in every family, and it passes with no mismatches against FalkorDB Cloud.&lt;/p&gt;

&lt;h2&gt;
  
  
  Careful wording
&lt;/h2&gt;

&lt;p&gt;A tool like this must not scare people or promise outcomes. It never says "you will get X". It says things like "higher chance" and "discuss this with a doctor or genetic counsellor", and it points to carrier screening, which is a simple blood test.&lt;/p&gt;

&lt;h2&gt;
  
  
  Update: try your own family
&lt;/h2&gt;

&lt;p&gt;After recording my demo video, I added a &lt;code&gt;/custom&lt;/code&gt; page where you can describe your own family of 20 to 50 people: nicknames, sex, who is affected, parents and partners. Click anyone for the same report as the demo families.&lt;/p&gt;

&lt;p&gt;For each report the app builds a temporary graph in FalkorDB with a random name, runs the same Cypher queries and exact genetics, then deletes the graph. Nothing is saved. Use nicknames, not real names.&lt;/p&gt;

&lt;p&gt;Two things made this possible. First, my original genetics code listed every genotype combination, which became too slow beyond about 20 people. I replaced it with variable elimination on the pedigree. It is still exact, and a 50-person family now takes a fraction of a second. I compared it with the original engine, and the results were identical on all 30 demo families.&lt;/p&gt;

&lt;p&gt;Second, there is now an AI chat for your own family. It only receives the family you entered and the report of the person you last clicked, and it quotes the numbers from that report instead of calculating its own. If you ask about someone whose report you haven't generated, it tells you to click them first. The family and your question are sent to Gemini to write the answer, and the app does not save them.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I would do next
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Run the probability maths inside the graph, or compare it against a graph algorithm.&lt;/li&gt;
&lt;li&gt;Add X-linked conditions and age of onset.&lt;/li&gt;
&lt;li&gt;Support larger families and more conditions.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Built with AI assistance
&lt;/h2&gt;

&lt;p&gt;Claude (Anthropic) helped design the approach and wrote much of the code, and Gemini is the LLM inside the agent. I came up with this idea, set up Docker and FalkorDB Cloud, ran and verified every script, enlarged the dataset, tested the app and agent, and deployed it on Render.&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Live demo: &lt;a href="https://pedigreegraph.onrender.com" rel="noopener noreferrer"&gt;https://pedigreegraph.onrender.com&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Code: &lt;a href="https://github.com/vani-crypto-tech/pedigreegraph" rel="noopener noreferrer"&gt;https://github.com/vani-crypto-tech/pedigreegraph&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Video: &lt;a href="https://youtu.be/-cMjirH7sjw" rel="noopener noreferrer"&gt;https://youtu.be/-cMjirH7sjw&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If a family tree is already a graph, maybe it's time we read it before it surprises us.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>hackathon</category>
      <category>python</category>
      <category>database</category>
    </item>
    <item>
      <title>PedigreeGraph: Built an AI agent that reads a family tree</title>
      <dc:creator>Vanya Mittal</dc:creator>
      <pubDate>Sun, 18 Oct 2026 11:03:02 +0000</pubDate>
      <link>https://dev.to/vanya_mittal_009fd2d47161/pedigreegraph-built-an-ai-agent-that-reads-a-family-tree-4m72</link>
      <guid>https://dev.to/vanya_mittal_009fd2d47161/pedigreegraph-built-an-ai-agent-that-reads-a-family-tree-4m72</guid>
      <description>&lt;p&gt;&lt;strong&gt;Built for Graph Hacks: Context for AI Agents (FalkorDB x WeMakeDevs), Track 01: Agents That Act on Connected Data.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The story nobody told
&lt;/h2&gt;

&lt;p&gt;Most of us know our families through stories: who laughed the loudest, who cooked the best, who we lost too soon. But some stories are never told, because nobody knew they were there.&lt;/p&gt;

&lt;p&gt;Beta-thalassemia is one of them. One ICMR estimate puts the number of carriers in India at 35 to 45 million, based on a carrier rate of roughly 3.5 to 4 per cent (&lt;a href="https://www.ncbi.nlm.nih.gov/pmc/articles/PMC4042365/" rel="noopener noreferrer"&gt;source&lt;/a&gt;). Other sources give slightly different figures, so read it as a rough scale. The hard part is that carriers usually have no symptoms, so they have no reason to suspect anything. When both partners are carriers, each pregnancy has a 25 per cent chance of a child born with thalassemia major (&lt;a href="https://www.thestatesman.com/supplements/science_supplements/thalassemia-is-a-silent-genetic-disorder-that-can-be-prevented-through-awareness-and-screening-1503432889.html" rel="noopener noreferrer"&gt;source&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Nobody in that story did anything wrong. They just didn't know.&lt;/p&gt;

&lt;p&gt;That made me think: the warning signs are often already in the family, in who is related to whom, who is affected, and who shares ancestors. That is a graph.&lt;/p&gt;

&lt;p&gt;My demo video: &lt;a href="https://youtu.be/-cMjirH7sjw" rel="noopener noreferrer"&gt;https://youtu.be/-cMjirH7sjw&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I built
&lt;/h2&gt;

&lt;p&gt;PedigreeGraph stores &lt;strong&gt;30 synthetic families (540 people)&lt;/strong&gt; in FalkorDB. An AI agent, running on Gemini, answers questions like "What is the risk picture for FAM1_P14?" or "Who should be tested first in FAM3?" by calling graph tools. Every answer shows the family path behind it, highlighted on a drawn pedigree. Clicking any person gives an instant report with no AI call at all.&lt;/p&gt;

&lt;p&gt;All data is synthetic. The condition names are real (beta-thalassemia, cystic fibrosis, sickle cell disease, Tay-Sachs disease, familial hypercholesterolemia), but only the inheritance pattern is modelled. This is family-history risk awareness, not a diagnosis.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Try it:&lt;/strong&gt; &lt;a href="https://pedigreegraph.onrender.com/" rel="noopener noreferrer"&gt;https://pedigreegraph.onrender.com/&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Try your own family:&lt;/strong&gt; &lt;a href="https://pedigreegraph.onrender.com/custom" rel="noopener noreferrer"&gt;https://pedigreegraph.onrender.com/custom&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  The graph model
&lt;/h2&gt;

&lt;p&gt;It is deliberately small:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cypher"&gt;&lt;code&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;:Person&lt;/span&gt; &lt;span class="ss"&gt;{&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt; &lt;span class="n"&gt;family&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt; &lt;span class="n"&gt;condition&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sex&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt; &lt;span class="n"&gt;generation&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt; &lt;span class="n"&gt;affected&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tested&lt;/span&gt;&lt;span class="ss"&gt;})&lt;/span&gt;
&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;:Person&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="ss"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;:PARENT_OF&lt;/span&gt;&lt;span class="ss"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;:Person&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;
&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;:Person&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="ss"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;:PARTNER_OF&lt;/span&gt;&lt;span class="ss"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;:Person&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is 540 people, 780 &lt;code&gt;PARENT_OF&lt;/code&gt; edges and 150 &lt;code&gt;PARTNER_OF&lt;/code&gt; edges. The graph only stores what a genetic counselor could observe. The true genotypes and the inheritance mode live outside it, so the agent can't cheat.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the graph does the work
&lt;/h2&gt;

&lt;p&gt;The questions that matter are about relationships, and they are multi-hop Cypher queries.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Obligate carriers.&lt;/strong&gt; An unaffected parent of an affected child must carry a recessive allele:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cypher"&gt;&lt;code&gt;&lt;span class="k"&gt;MATCH&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="py"&gt;par:&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt; &lt;span class="ss"&gt;{&lt;/span&gt;&lt;span class="py"&gt;family:&lt;/span&gt;&lt;span class="n"&gt;$fam&lt;/span&gt;&lt;span class="ss"&gt;})&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="ss"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;:PARENT_OF&lt;/span&gt;&lt;span class="ss"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="py"&gt;c:&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt; &lt;span class="ss"&gt;{&lt;/span&gt;&lt;span class="py"&gt;family:&lt;/span&gt;&lt;span class="n"&gt;$fam&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt; &lt;span class="py"&gt;affected:&lt;/span&gt;&lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="ss"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="ow"&gt;NOT&lt;/span&gt; &lt;span class="n"&gt;par.affected&lt;/span&gt;
&lt;span class="k"&gt;RETURN&lt;/span&gt; &lt;span class="n"&gt;par.id&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;collect&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c.id&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Shared ancestors.&lt;/strong&gt; Two partners are related if they descend from the same person. Two variable-length patterns meet at the same ancestor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cypher"&gt;&lt;code&gt;&lt;span class="k"&gt;MATCH&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="py"&gt;a:&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt; &lt;span class="ss"&gt;{&lt;/span&gt;&lt;span class="py"&gt;family:&lt;/span&gt;&lt;span class="n"&gt;$fam&lt;/span&gt;&lt;span class="ss"&gt;})&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="ss"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;:PARTNER_OF&lt;/span&gt;&lt;span class="ss"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="py"&gt;b:&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt; &lt;span class="ss"&gt;{&lt;/span&gt;&lt;span class="py"&gt;family:&lt;/span&gt;&lt;span class="n"&gt;$fam&lt;/span&gt;&lt;span class="ss"&gt;}),&lt;/span&gt;
      &lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="py"&gt;anc:&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="ss"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;:PARENT_OF&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="ss"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="ss"&gt;),&lt;/span&gt;
      &lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="n"&gt;anc&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="ss"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;:PARENT_OF&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="ss"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;RETURN&lt;/span&gt; &lt;span class="n"&gt;a.id&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b.id&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;collect&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="k"&gt;DISTINCT&lt;/span&gt; &lt;span class="n"&gt;anc.id&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The shortest family path&lt;/strong&gt; from a person to the nearest affected relative. This becomes the red line on the tree:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cypher"&gt;&lt;code&gt;&lt;span class="k"&gt;MATCH&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="py"&gt;a:&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt; &lt;span class="ss"&gt;{&lt;/span&gt;&lt;span class="py"&gt;id:&lt;/span&gt;&lt;span class="n"&gt;$id&lt;/span&gt;&lt;span class="ss"&gt;})&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="ss"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;:PARENT_OF&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="m"&gt;6&lt;/span&gt;&lt;span class="ss"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="py"&gt;b:&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt; &lt;span class="ss"&gt;{&lt;/span&gt;&lt;span class="py"&gt;family:&lt;/span&gt;&lt;span class="n"&gt;$fam&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt; &lt;span class="py"&gt;affected:&lt;/span&gt;&lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="ss"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;b.id&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;$id&lt;/span&gt;
&lt;span class="k"&gt;RETURN&lt;/span&gt; &lt;span class="ss"&gt;[&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="ow"&gt;IN&lt;/span&gt; &lt;span class="nf"&gt;nodes&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;n.id&lt;/span&gt;&lt;span class="ss"&gt;]&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;length&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;hops&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;hops&lt;/span&gt; &lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are also queries for each person's affected relatives, from siblings and grandparents to aunts, uncles, nieces and nephews.&lt;/p&gt;

&lt;p&gt;In the demo family FAM1, two cousins (FAM1_P10 and FAM1_P14) are partners and already have an affected child. The graph finds their shared grandparents on its own, and the exact genetics gives a 25 percent chance for each future child.&lt;/p&gt;

&lt;h2&gt;
  
  
  The AI never does the maths
&lt;/h2&gt;

&lt;p&gt;The language model never calculates risk. It chooses tools and explains the results. The probabilities come from deterministic code that uses exact variable elimination on the pedigree, so a shared ancestor is counted correctly.&lt;/p&gt;

&lt;p&gt;One honest limitation: that calculation runs in Python over the family structure read from FalkorDB, not inside the database.&lt;/p&gt;

&lt;p&gt;To check the graph side, I wrote &lt;code&gt;test_cypher.py&lt;/code&gt;. It compares every Cypher query with an independent pure-Python implementation for every person in every family, and it passes with no mismatches against FalkorDB Cloud.&lt;/p&gt;

&lt;h2&gt;
  
  
  Careful wording
&lt;/h2&gt;

&lt;p&gt;A tool like this must not scare people or promise outcomes. It never says "you will get X". It says things like "higher chance" and "discuss this with a doctor or genetic counsellor", and it points to carrier screening, which is a simple blood test.&lt;/p&gt;

&lt;h2&gt;
  
  
  Update: try your own family
&lt;/h2&gt;

&lt;p&gt;After recording my demo video, I added a &lt;code&gt;/custom&lt;/code&gt; page where you can describe your own family of 20 to 50 people: nicknames, sex, who is affected, parents and partners. Click anyone for the same report as the demo families.&lt;/p&gt;

&lt;p&gt;For each report the app builds a temporary graph in FalkorDB with a random name, runs the same Cypher queries and exact genetics, then deletes the graph. Nothing is saved. Use nicknames, not real names.&lt;/p&gt;

&lt;p&gt;Two things made this possible. First, my original genetics code listed every genotype combination, which became too slow beyond about 20 people. I replaced it with variable elimination on the pedigree. It is still exact, and a 50-person family now takes a fraction of a second. I compared it with the original engine, and the results were identical on all 30 demo families.&lt;/p&gt;

&lt;p&gt;Second, there is now an AI chat for your own family. It only receives the family you entered and the report of the person you last clicked, and it quotes the numbers from that report instead of calculating its own. If you ask about someone whose report you haven't generated, it tells you to click them first. The family and your question are sent to Gemini to write the answer, and the app does not save them.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I would do next
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Run the probability maths inside the graph, or compare it against a graph algorithm.&lt;/li&gt;
&lt;li&gt;Add X-linked conditions and age of onset.&lt;/li&gt;
&lt;li&gt;Support larger families and more conditions.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Built with AI assistance
&lt;/h2&gt;

&lt;p&gt;Claude (Anthropic) helped design the approach and wrote much of the code, and Gemini is the LLM inside the agent. I came up with this idea, set up Docker and FalkorDB Cloud, ran and verified every script, enlarged the dataset, tested the app and agent, and deployed it on Render.&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Live demo: &lt;a href="https://pedigreegraph.onrender.com" rel="noopener noreferrer"&gt;https://pedigreegraph.onrender.com&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Code: &lt;a href="https://github.com/vani-crypto-tech/pedigreegraph" rel="noopener noreferrer"&gt;https://github.com/vani-crypto-tech/pedigreegraph&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Video: &lt;a href="https://youtu.be/-cMjirH7sjw" rel="noopener noreferrer"&gt;https://youtu.be/-cMjirH7sjw&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If a family tree is already a graph, maybe it's time we read it before it surprises us.&lt;/p&gt;

</description>
      <category>hackathon</category>
      <category>ai</category>
      <category>database</category>
      <category>python</category>
    </item>
  </channel>
</rss>
