> ## Documentation Index
> Fetch the complete documentation index at: https://docs.learningcommons.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Generating prerequisite practice questions

> Learn how to use Knowledge Graph learning progressions to find prerequisite standards and generate practice content with LLMs.

export const EarlyAccessCallout = ({children}) => <div className="eyebrow-callout not-prose rounded-xl border border-gray-200/80 p-5 dark:border-white/10" style={{
  marginBottom: "1rem",
  borderRadius: "4px"
}}>
    <div className="mb-3">
      <Badge color="green" size="md" icon="flask">
        Early access
      </Badge>
    </div>
    <div className="callout-body text-[15px] leading-relaxed text-gray-700 dark:text-gray-300">{children}</div>
    <style>{`.callout-body a { text-decoration: underline; text-decoration-color: #178251; }`}</style>
  </div>;

<EarlyAccessCallout>
  The API is in early access and is actively evolving. We will continue expanding it, and breaking changes may occur as we improve accuracy and reliability. Email [support@learningcommons.org](mailto:support@learningcommons.org) ↗ with your feedback or issues.
</EarlyAccessCallout>

In this tutorial, you will use Knowledge Graph to query prerequisite standards for a given standard, enabling differentiated content or product experiences.

## Before you begin

There are a couple of things you need to know about the dataset:

* Our current learning progressions dataset, from [Student Achievement Partners](https://learnwithsap.org/) ↗ (SAP), map Common Core State Standards for Mathematics into logical sequences.
* The sequences **do not** name definitive pre-reqs. Meaning, it is not necessarily true that students *must* master an earlier standard before they will be ready for the standards it supports. Instead, the relationships indicate what might be helpful in a given circumstance.

To learn more about these entities, read the data references for [Academic Standards](../../entity-and-relationship-reference/academic-standards) and [Learning Progressions](../../entity-and-relationship-reference/learning-progressions).

<Frame>
  <img src="https://mintcdn.com/czi-60a2a443/bb-F2r75Gz83PPsi/images/kg/coherence-map-dataset_data-model-diagram_high-level.svg?fit=max&auto=format&n=bb-F2r75Gz83PPsi&q=85&s=65f4a6d966366569e055e38bbba6e055" alt="Data model diagram: StandardsFrameworkItem nodes connected by buildsTowards and relatesTo (Coherence Map learning progressions)" width="1384" height="900" data-path="images/kg/coherence-map-dataset_data-model-diagram_high-level.svg" />
</Frame>

<Accordion title="Diagram description">
  The diagram shows only **learning progressions** (Coherence Map). The entity `StandardsFrameworkItem` is defined in [Academic standards](/knowledge-graph/entity-and-relationship-reference/academic-standards); [Learning progressions](/knowledge-graph/entity-and-relationship-reference/learning-progressions) documents the progression relationships between items.

  **Example (CCSSM):** Every node is a **standard** (a `StandardsFrameworkItem` from Common Core Math). A **buildsTowards** edge means earlier proficiency supports later—e.g. *3.OA.A.1 (Interpret products)* buildsTowards *4.NBT.B.5 (Multiply multi-digit numbers)*. A **relatesTo** edge links standards that are conceptually related without a fixed sequence—e.g. *3.NF.A.1* might relateTo *3.NF.A.2* (same domain, reinforcing ideas). The diagram does not show the full standards hierarchy (framework → domain → standard); only progression links between standards.

  **Edge list (source → relationship → target):**

  * `StandardsFrameworkItem` → `buildsTowards` → `StandardsFrameworkItem` (e.g. 3.OA.A.1 → 4.NBT.B.5)
  * `StandardsFrameworkItem` → `relatesTo` → `StandardsFrameworkItem` (e.g. 3.NF.A.1 ↔ 3.NF.A.2)
</Accordion>

## What you'll do

* Navigating learning progressions relationships
* Unpacking standards into learning components
* Inserting Knowledge Graph data into LLM context for content generation

## What you'll need

* A [Learning Commons Platform](https://platform.learningcommons.org/) ↗ account
* An API key generated in the platform
* Node or Python for running code examples
* OpenAI API key for generating practice questions
* OpenAI SDK installed (`pip install openai` for Python or `npm install openai` for JavaScript)

## STEP 1: Set up environment variables

1. Set up your environment variables for your API key, base URL, and OpenAI.

```shell theme={null}
# .env

# Knowledge Graph API credentials - get these from the Learning Commons Portal
API_KEY=your_api_key_here
BASE_URL=https://api.learningcommons.org/knowledge-graph/v0

# OpenAI API key for generating practice questions
OPENAI_API_KEY=your_openai_api_key_here
```

## STEP 2: Get prerequisite standards for 6.NS.B.4

1. Use the `/academic-standards/search` endpoint to find the standard, then use the `/prerequisites` endpoint to get its prerequisites:

<CodeGroup>
  ```shell cURL theme={null}
  # Step 1: Find the target standard by statement code
  curl -X GET \
    -H "x-api-key: YOUR_API_KEY" \
    "https://api.learningcommons.org/knowledge-graph/v0/academic-standards/search?statementCode=6.NS.B.4&jurisdiction=Multi-State"

  # Step 2: Get prerequisites using the caseIdentifierUUID from Step 1
  curl -X GET \
    -H "x-api-key: YOUR_API_KEY" \
    "https://api.learningcommons.org/knowledge-graph/v0/academic-standards/YOUR_UUID/prerequisites"
  ```

  ```python Python theme={null}
  import os
  import requests

  api_key = os.getenv("API_KEY")
  base_url = os.getenv("BASE_URL")
  TARGET_CODE = "6.NS.B.4"

  headers = {"x-api-key": api_key}

  # Find the target standard by statement code
  search_response = requests.get(
      f"{base_url}/academic-standards/search",
      headers=headers,
      params={
          "statementCode": TARGET_CODE,
          "jurisdiction": "Multi-State"
      }
  )

  search_result = search_response.json()
  target_standard = search_result[0] if search_result else None

  if not target_standard:
      print(f'❌ No standard found for {TARGET_CODE}')
  else:
      print(f'✅ Found standard {TARGET_CODE}:')
      print(f'  UUID: {target_standard["caseIdentifierUUID"]}')
      print(f'  Description: {target_standard["description"]}')

      # Get prerequisites
      prereq_response = requests.get(
          f"{base_url}/academic-standards/{target_standard['caseIdentifierUUID']}/prerequisites",
          headers=headers
      )

      prereq_result = prereq_response.json()
      prerequisite_standards = prereq_result["data"]
      print(f'✅ Found {len(prerequisite_standards)} prerequisite(s):')
      for prereq in prerequisite_standards:
          print(f'  {prereq["statementCode"]}: {prereq["description"][:80]}...')
  ```

  ```javascript JavaScript theme={null}
  const apiKey = process.env.API_KEY;
  const baseUrl = process.env.BASE_URL;
  const TARGET_CODE = "6.NS.B.4";

  // Find the target standard by statement code
  const searchResponse = await fetch(
    `${baseUrl}/academic-standards/search?statementCode=${TARGET_CODE}&jurisdiction=Multi-State`,
    {
      method: 'GET',
      headers: { 'x-api-key': apiKey }
    }
  );

  const searchResult = await searchResponse.json();
  const targetStandard = searchResult[0] || null;

  if (!targetStandard) {
    console.error(`❌ No standard found for ${TARGET_CODE}`);
  } else {
    console.log(`✅ Found standard ${TARGET_CODE}:`);
    console.log(`  UUID: ${targetStandard.caseIdentifierUUID}`);
    console.log(`  Description: ${targetStandard.description}`);

    // Get prerequisites
    const prereqResponse = await fetch(
      `${baseUrl}/academic-standards/${targetStandard.caseIdentifierUUID}/prerequisites`,
      {
        method: 'GET',
        headers: { 'x-api-key': apiKey }
      }
    );

    const prereqResult = await prereqResponse.json();
    const prerequisiteStandards = prereqResult.data;
    console.log(`✅ Found ${prerequisiteStandards.length} prerequisite(s):`);
    prerequisiteStandards.forEach(prereq => {
      console.log(`  ${prereq.statementCode}: ${prereq.description.substring(0, 80)}...`);
    });
  }
  ```
</CodeGroup>

The data for the specific standard should look like this:

```json theme={null}
[
  {
    "caseIdentifierUUID": "6b9ed00e-d7cc-11e8-824f-0242ac160002",
    "statementCode": "4.OA.B.4",
    "standardDescription": "A buildsTowards relationship indicates that proficiency in one entity supports the likelihood of success in another, capturing a directional progression without requiring strict prerequisite order."
  },
  // ...
]
```

2. Find the learning components that support the prerequisite standards that we just found using the `/learning-components` endpoint for each prerequisite standard:

<CodeGroup>
  ```shell cURL theme={null}
  # Get learning components for a prerequisite standard
  # Replace PREREQ_UUID with each prerequisite's caseIdentifierUUID
  curl -X GET \
    -H "x-api-key: YOUR_API_KEY" \
    "https://api.learningcommons.org/knowledge-graph/v0/academic-standards/PREREQ_UUID/learning-components"
  ```

  ```python Python theme={null}
  import os
  import requests

  api_key = os.getenv("API_KEY")
  base_url = os.getenv("BASE_URL")

  headers = {"x-api-key": api_key}

  # prerequisite_standards from previous step
  prerequisite_learning_components = []

  for prereq in prerequisite_standards:
      lc_response = requests.get(
          f"{base_url}/academic-standards/{prereq['caseIdentifierUUID']}/learning-components",
          headers=headers
      )
      
      lc_result = lc_response.json()
      for lc in lc_result["data"]:
          prerequisite_learning_components.append({
              "caseIdentifierUUID": prereq["caseIdentifierUUID"],
              "statementCode": prereq["statementCode"],
              "standardDescription": prereq["description"],
              "learningComponentDescription": lc["description"]
          })

  print(f'✅ Found {len(prerequisite_learning_components)} supporting learning components for prerequisites:')
  for lc in prerequisite_learning_components[:5]:
      print(f'  {lc["learningComponentDescription"][:80]}...')
  ```

  ```javascript JavaScript theme={null}
  const apiKey = process.env.API_KEY;
  const baseUrl = process.env.BASE_URL;

  // prerequisiteStandards from previous step
  const prerequisiteLearningComponents = [];

  for (const prereq of prerequisiteStandards) {
    const lcResponse = await fetch(
      `${baseUrl}/academic-standards/${prereq.caseIdentifierUUID}/learning-components`,
      {
        method: 'GET',
        headers: { 'x-api-key': apiKey }
      }
    );
    
    const lcResult = await lcResponse.json();
    for (const lc of lcResult.data) {
      prerequisiteLearningComponents.push({
        caseIdentifierUUID: prereq.caseIdentifierUUID,
        statementCode: prereq.statementCode,
        standardDescription: prereq.description,
        learningComponentDescription: lc.description
      });
    }
  }

  console.log(`✅ Found ${prerequisiteLearningComponents.length} supporting learning components for prerequisites:`);
  prerequisiteLearningComponents.slice(0, 5).forEach(lc => {
    console.log(`  ${lc.learningComponentDescription.substring(0, 80)}...`);
  });
  ```
</CodeGroup>

The learning components and prerequisite standards data should look like this:

```json theme={null}
[
  {
    "caseIdentifierUUID": "6b9d5f43-d7cc-11e8-824f-0242ac160002",
    "statementCode": "5.OA.A.2",
    "standardDescription": "A buildsTowards relationship indicates that proficiency in one entity supports the likelihood of success in another, capturing a directional progression without requiring strict prerequisite order.",
    "learningComponentDescription": "Write simple expressions of two or more steps and with grouping symbols that record calculations with numbers"
  },
  // ...
]
```

The `prerequisiteLearningComponents` array is ready to be used for generating practice questions in Step 3.

## STEP 3: Generate practice problems

Now that you've identified learning components and prerequisite standards, you can use those for downstream applications, such as generating practice problems. But remember the caveats discussed above and use your judgment to create appropriate learning experiences.

1. Create clean JSON to package the data, making it easily parsable by the LLM and preserving the data's relationship structure.

<CodeGroup>
  ```javascript Javascript theme={null}
  function packageContextData(targetStandard, prerequisiteLearningComponents) {
    /* Package the standards and learning components data for text generation
     * This creates a structured context that can be used for generating practice questions
     */

    const standardsMap = new Map();

    // Group learning components by standard for context
    for (const row of prerequisiteLearningComponents) {
      if (!standardsMap.has(row.caseIdentifierUUID)) {
        standardsMap.set(row.caseIdentifierUUID, {
          statementCode: row.statementCode,
          description: row.standardDescription || '(no statement)',
          supportingLearningComponents: []
        });
      }

      standardsMap.get(row.caseIdentifierUUID).supportingLearningComponents.push({
        description: row.learningComponentDescription || '(no description)'
      });
    }

    const fullStandardsContext = {
      targetStandard: {
        statementCode: targetStandard.statementCode,
        description: targetStandard.description || '(no statement)'
      },
      prereqStandards: Array.from(standardsMap.values())
    };
    
    return fullStandardsContext;
  }
  ```

  ```python Python theme={null}
  def package_context_data(target_standard, prerequisite_learning_components):
      """
      Package the standards and learning components data for text generation
      This creates a structured context that can be used for generating practice questions
      """

      standards_map = {}

      # Group learning components by standard for context
      for row in prerequisite_learning_components:
          case_id = row['caseIdentifierUUID']
          if case_id not in standards_map:
              standards_map[case_id] = {
                  'statementCode': row['statementCode'],
                  'description': row['standardDescription'] or '(no statement)',
                  'supportingLearningComponents': []
              }

          standards_map[case_id]['supportingLearningComponents'].append({
              'description': row['learningComponentDescription'] or '(no description)'
          })

      full_standards_context = {
          'targetStandard': {
              'statementCode': target_standard['statementCode'],
              'description': target_standard['description'] or '(no statement)'
          },
          'prereqStandards': list(standards_map.values())
      }

      print('✅ Packaged full standards context for text generation')
      return full_standards_context
  ```
</CodeGroup>

2. Use that JSON in a prompt so the LLM has full context of what to create practice problems for.

<CodeGroup>
  ```javascript Javascript theme={null}
  const OpenAI = require('openai');

  const openai = new OpenAI({
    apiKey: process.env.OPENAI_API_KEY,
  });

  const OPENAI_MODEL = 'gpt-4';
  const OPENAI_TEMPERATURE = 0.7;

  async function generatePractice(fullStandardsContext) {
    console.log(`🔄 Generating practice questions for ${fullStandardsContext.targetStandard.statementCode}...`);

    try {
      // Build prompt inline
      let prerequisiteText = '';
      for (const prereq of fullStandardsContext.prereqStandards) {
        prerequisiteText += `- ${prereq.statementCode}: ${prereq.description}\n`;
        prerequisiteText += '  Supporting Learning Components:\n';
        for (const lc of prereq.supportingLearningComponents) {
          prerequisiteText += `    • ${lc.description}\n`;
        }
      }

      const prompt = `You are a math tutor helping middle school students. Based on the following information, generate 3 practice questions for the target standard. Questions should help reinforce the key concept and build on prerequisite knowledge.

  Target Standard:
  - ${fullStandardsContext.targetStandard.statementCode}: ${fullStandardsContext.targetStandard.description}

  Prerequisite Standards & Supporting Learning Components:
  ${prerequisiteText}`;

      const response = await openai.chat.completions.create({
        model: OPENAI_MODEL,
        messages: [
          { role: 'system', content: 'You are an expert middle school math tutor.' },
          { role: 'user', content: prompt }
        ],
        temperature: OPENAI_TEMPERATURE
      });

      const practiceQuestions = response.choices[0].message.content.trim();

      console.log(`✅ Generated practice questions:\n`);
      console.log(practiceQuestions);

      return {
        aiGenerated: practiceQuestions,
        targetStandard: fullStandardsContext.targetStandard.statementCode,
        prerequisiteCount: fullStandardsContext.prereqStandards.length
      };
    } catch (err) {
      console.error('❌ Error generating practice questions:', err.message);
      throw err;
    }
  }
  ```

  ```python Python theme={null}
  from openai import OpenAI

  openai_client = OpenAI(
      api_key=os.getenv('OPENAI_API_KEY')
  )

  OPENAI_MODEL = 'gpt-4'
  OPENAI_TEMPERATURE = 0.7

  def generate_practice(full_standards_context):
      print(f'🔄 Generating practice questions for {full_standards_context["targetStandard"]["statementCode"]}...')

      try:
          # Build prompt inline
          prerequisite_text = ''
          for prereq in full_standards_context['prereqStandards']:
              prerequisite_text += f'- {prereq["statementCode"]}: {prereq["description"]}\n'
              prerequisite_text += '  Supporting Learning Components:\n'
              for lc in prereq['supportingLearningComponents']:
                  prerequisite_text += f'    • {lc["description"]}\n'

          prompt = f"""You are a math tutor helping middle school students. Based on the following information, generate 3 practice questions for the target standard. Questions should help reinforce the key concept and build on prerequisite knowledge.

  Target Standard:
  - {full_standards_context["targetStandard"]["statementCode"]}: {full_standards_context["targetStandard"]["description"]}

  Prerequisite Standards & Supporting Learning Components:
  {prerequisite_text}"""

          response = openai_client.chat.completions.create(
              model=OPENAI_MODEL,
              messages=[
                  {'role': 'system', 'content': 'You are an expert middle school math tutor.'},
                  {'role': 'user', 'content': prompt}
              ],
              temperature=OPENAI_TEMPERATURE
          )

          practice_questions = response.choices[0].message.content.strip()

          print('✅ Generated practice questions:\n')
          print(practice_questions)

          return {
              'aiGenerated': practice_questions,
              'targetStandard': full_standards_context['targetStandard']['statementCode'],
              'prerequisiteCount': len(full_standards_context['prereqStandards'])
          }
      except Exception as err:
          print(f'❌ Error generating practice questions: {str(err)}')
          raise err
  ```
</CodeGroup>

The resulting generated problems should look something like this:

```text theme={null}
Question 1: 
Find the greatest common factor of 36 and 90. Then use the distributive property to express the sum of these two numbers as a multiple of a sum of two whole numbers with no common factor.

Question 2: 
Write the expression "add 12 and 15, then multiply by 3" as an algebraic expression. After that, recognize that this expression is three times as large as 12 + 15, without having to calculate the indicated sum or product.

Question 3: 
Determine whether the number 72 is a multiple of the digit 8. Find all factor pairs of 72. Recognize that 72 is a multiple of each of its factors and determine whether 72 is a prime or a composite number.
```

<Tip>
  Everything here was scoped to a single standard for clarity, but the same steps work across grade levels, subject areas, or even larger parts of the dataset. Try extending the queries to include lessons, assessments, or instructional routines to create more comprehensive learning experiences.
</Tip>
