Our current Learning
Progressions dataset
from Student Achievement Partners ↗ (SAP)
maps Common Core State Standards for Mathematics into logical sequences. These
sequences do not name definitive prerequisites – their relationships simply
indicate what might be helpful in a given circumstance.
What you’ll do
- Find prerequisite standards for a target CCSS standard using Learning Progressions
- Unpack prerequisite standards into supporting Learning Components
- Package Knowledge Graph data for an LLM to generate practice questions
What you’ll need
- API key and base URL in the Learning Commons Platform ↗
- OpenAI API key and SDK (
pip install openaifor Python ornpm install openaifor JavaScript) curl↗, Python, or Node
Steps
1
Set up environment variables
.env
API_KEY=your_api_key_here
BASE_URL=https://api.learningcommons.org/knowledge-graph/v0
OPENAI_API_KEY=your_openai_api_key_here
2
Get the prerequisite standards for 6.NS.B.4
Use the
GET /academic-standards/search endpoint to find the 6.NS.B.4 standard.Then, use GET /academic-standards/{uuid}/prerequisites to get its prerequisites:# 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"
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]}...')
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)}...`,
);
});
}
Response
[
{
"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."
}
// ...
]
3
Get Learning Components for the prerequisite standards
Use the You will use the
GET /academic-standards/{uuid}/learning-components endpoint for each prerequisite standard:# 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"
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]}...')
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)}...`);
});
Response
[
{
"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"
}
// ...
]
prerequisiteLearningComponents array to generate practice questions in the next step.4
Generate practice problems
Package the Academic Standards and Learning Components data to generate practice questions.Use that JSON in a prompt so the LLM has full context when creating practice questions:You can now integrate these practice questions into your product workflow!
function packageContextData(targetStandard, prerequisiteLearningComponents) {
// Package the Academic Standards and Learning Components data for text generation
const standardsMap = new Map();
// Group Learning Components by Academic 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;
}
def package_context_data(target_standard, prerequisite_learning_components):
# Package the Academic Standards and Learning Components data for text generation
standards_map = {}
# Group Learning Components by Academic 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
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;
}
}
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
Example response
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.
5
Keep exploring
We scoped to a single standard for clarity, but you can also extend prerequisite chains across grade levels or explore other target standards and subject areas.For more comprehensive learning experiences, extend your queries to include lessons, assessments, or instructional routines.