Skip to content
Kavyasri Jadala
All work
Enterprise · public companionsGenAI · Recommendation · Content lineage · Knowledge graph

Governed Content Intelligence

In pharma, AI may only recommend or generate medically, legally and regulatory-approved content — and someone must prove which approved claim each sentence came from.

My role. Owned the content-lineage data product and GenAI market adaptation

per-market dossier adaptation
~3 mo → 1 wkper-market dossier adaptation
markets, incl. 6 low- & middle-income
~25markets, incl. 6 low- & middle-income
lineage to source and approval
Slide-levellineage to source and approval
  • GenAI
  • Knowledge graph
  • Lineage
  • Recommendation
  • FastAPI
  • python-pptx

Architecture reconstructed with synthetic data; proprietary implementation excluded.

01Problem

In pharma, AI may only recommend or generate content that has passed medical, legal and regulatory (MLR) review — and someone must be able to prove which approved claim each sentence came from. Market-access teams also present the same reimbursement evidence in a different format for every country: adapting one dossier took about three months, so smaller markets waited quarters before patients could get the drug reimbursed.

02Context

  • Users: brand, field and market-access teams; MLR reviewers; regional affiliates.
  • Constraint: generative AI is fast but ungoverned; regulated content is governed but slow. Without lineage, nothing generated is usable.
  • Goal: recommendations and generated documents built only from approved content, with lineage that survives an audit.

03Data

  • Customer signals: profile, specialty and engagement history.
  • Content metadata: asset, key message, claim, supporting evidence, approval status and approval ID, market, expiry.
  • Lineage edges: which slide or message used which claim, which claim rests on which evidence, which approval covers it.

04Architecture

Recommend and generate only what can be traced
  1. Customerprofile · specialty
  2. Interactionsengagement history
  3. Content / metadata graphasset → claim → evidence → approval
  4. Eligibility filterapproved · in-market · not expired
  5. Ranking / recommendationrelevance among eligible content
  6. Generated outputslides, dossiers, messages
  7. Evidence / content lineageevery sentence → source + approval ID

Eligibility comes before ranking and is deterministic. A model decides what is most relevant; it never decides what is allowed.

05What I built

  • The content-lineage data product at Bristol Myers Squibb.
  • GenAI market adaptation of reimbursement dossiers, replacing agency drafting so markets could file in parallel.
  • Two public companions on synthetic data: a governance catalog with impact and provenance analysis, and a governed slide generator.

The generation gate from the public slide generator — a claim that is not approved never reaches a slide, and every slide that is rendered carries its approval:

governed-slide-generator/src/build_deck.pysource ↗
    lineage, skipped = [], []
  for item in content["items"]:
      if item["mlr_status"] != "Approved":     # governance gate
          skipped.append({"title": item["title"], "reason": f"MLR status {item['mlr_status']}"})
          continue
      _add_claim_slide(prs, item)
      lineage.append({
          "slide_title": item["title"],
          "content_id": item["content_id"],
          "mlr_approval_id": item["mlr_approval_id"],
          "source_ref": item["source_ref"],
      })

06Modeling / AI approach

  • Constrain, don't filter. The generator is populated only from approved content, instead of generating freely and checking afterwards.
  • Lineage is a graph. Impact ("what changes if this claim is withdrawn?") is a descendants query; provenance ("where did this sentence come from?") is an ancestors query:
commercial-metadata-catalog/src/catalog.pysource ↗
def build_lineage(edges):
  g = nx.DiGraph()
  for e in edges:
      g.add_edge(e["from"], e["to"], via=e["via"])
  return g


def impact(g, node):
  return sorted(nx.descendants(g, node)) if node in g else []


def provenance(g, node):
  return sorted(nx.ancestors(g, node)) if node in g else []


def sources_reached(g, node):
  """Upstream nodes that are themselves sources (no upstream of their own)."""
  return [n for n in nx.ancestors(g, node) if g.in_degree(n) == 0] if node in g else []

07Evaluation

  • The governance checks run like tests: every dataset owned and classified, every KPI traced to a source, every generated slide traced through key message → MLR approval → content → source asset.
  • In the public generator demo, three approved claims render and the one claim still in review is refused — a mechanism check, not a production benchmark.
  • Withdrawing an approved claim lists exactly which assets it touches.

08Production considerations

  • Served through an API (FastAPI in the public rebuild) so every downstream tool inherits the same gate.
  • Lineage is written into the artifact itself (speaker notes) and a sidecar record, so it survives when a file is emailed out of the system.

09Results

  • Per-market dossier adaptation: ~3 months → ~1 week.
  • Rolled across ~25 markets, including 6 low- and middle-income countries that had previously waited longest.
  • Slide-level lineage from generated output to source evidence and approval.

10Tradeoffs / lessons

  • Lineage at the slide level, not the document level. Document-level lineage cannot answer the question an auditor actually asks.
  • Generation is only as fast as review. Carrying the approval ID with every piece of content is what lets a reviewer check a draft instead of re-researching it.
In regulated GenAI, lineage is the product. Speed only becomes usable once every sentence can be traced.