Skip to content

Commit

Permalink
Rename AI files (#1860)
Browse files Browse the repository at this point in the history
## Summary:

[There was discussion around the names of things in the AI folder being confusing.](https://khanacademy.slack.com/archives/C01AZ9H8TTQ/p1731537082583919)

What this PR does:
1. renames `prompt-utils.ts` files to `[widget]-ai-utils.ts`
2. most of these directories had two test files (1) testing `getPromptJSON` directly and (2) testing `getPromptJSON` on the widget export; I just combined these test files and renamed them to `[widget]-ai-utils.test.ts`
3. updates the REAME

No real logic changes, just code shoveling.

Author: handeyeco

Reviewers: SonicScrewdriver, handeyeco

Required Reviewers:

Approved By: SonicScrewdriver

Checks: ✅ Publish npm snapshot (ubuntu-latest, 20.x), ✅ Lint, Typecheck, Format, and Test (ubuntu-latest, 20.x), ✅ Cypress (ubuntu-latest, 20.x), ✅ Check for .changeset entries for all changed files (ubuntu-latest, 20.x), ✅ Check builds for changes in size (ubuntu-latest, 20.x), ✅ Publish Storybook to Chromatic (ubuntu-latest, 20.x), ✅ gerald

Pull Request URL: #1860
  • Loading branch information
handeyeco authored Nov 15, 2024
1 parent 892cce6 commit 9c2289b
Show file tree
Hide file tree
Showing 122 changed files with 1,755 additions and 1,665 deletions.
5 changes: 5 additions & 0 deletions .changeset/nasty-bikes-travel.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@khanacademy/perseus": patch
---

Rename AI util files
5 changes: 4 additions & 1 deletion packages/perseus/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -255,4 +255,7 @@ export type {
TagsShape,
} from "./multi-items/shape-types";
export type {Path} from "./multi-items/trees";
export type {RendererPromptJSON, WidgetPromptJSON} from "./prompt-types";
export type {
RendererPromptJSON,
WidgetPromptJSON,
} from "./widget-ai-utils/prompt-types";
68 changes: 0 additions & 68 deletions packages/perseus/src/prompt-types.ts

This file was deleted.

5 changes: 4 additions & 1 deletion packages/perseus/src/renderer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ import type {
PerseusWidgetsMap,
ShowSolutions,
} from "./perseus-types";
import type {GetPromptJSONInterface, RendererPromptJSON} from "./prompt-types";
import type {PerseusStrings} from "./strings";
import type {
APIOptions,
Expand All @@ -53,6 +52,10 @@ import type {
WidgetProps,
} from "./types";
import type {UserInputArray, UserInputMap} from "./validation.types";
import type {
GetPromptJSONInterface,
RendererPromptJSON,
} from "./widget-ai-utils/prompt-types";
import type {KeypadAPI} from "@khanacademy/math-input";
import type {LinterContextProps} from "@khanacademy/perseus-linter";

Expand Down
5 changes: 4 additions & 1 deletion packages/perseus/src/server-item-renderer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,15 @@ import Renderer from "./renderer";
import Util from "./util";

import type {PerseusItem, ShowSolutions} from "./perseus-types";
import type {GetPromptJSONInterface, RendererPromptJSON} from "./prompt-types";
import type {
FocusPath,
PerseusDependenciesV2,
SharedRendererProps,
} from "./types";
import type {
GetPromptJSONInterface,
RendererPromptJSON,
} from "./widget-ai-utils/prompt-types";
import type {KeypadAPI} from "@khanacademy/math-input";
import type {
KeypadContextRendererInterface,
Expand Down
2 changes: 1 addition & 1 deletion packages/perseus/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import type {
PerseusWidget,
PerseusWidgetsMap,
} from "./perseus-types";
import type {WidgetPromptJSON} from "./prompt-types";
import type {PerseusStrings} from "./strings";
import type {SizeClass} from "./util/sizing-utils";
import type {
Expand All @@ -16,6 +15,7 @@ import type {
UserInputArray,
UserInputMap,
} from "./validation.types";
import type {WidgetPromptJSON} from "./widget-ai-utils/prompt-types";
import type {KeypadAPI} from "@khanacademy/math-input";
import type {AnalyticsEventHandlerFn} from "@khanacademy/perseus-core";
import type {LinterContextProps} from "@khanacademy/perseus-linter";
Expand Down
30 changes: 20 additions & 10 deletions packages/perseus/src/widget-ai-utils/README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,25 @@
# What are these utilities for?
# Widget AI utils

We want to have a representation of Perseus widgets that LLMs can understand.
They understand JSON pretty well! This is a set of utility functions for each
widget that get the minimum amount of data for an LLM to understand the state
of the widget, as well as the current user input.
> [!CAUTION]
> This code is not meant to be interwoven with Perseus' core logic.
> We want to keep it as isolated as possible from the rest of Perseus.
> [!CAUTION]
> Please be cautious making changes within this folder,
> it's an external API consumed by the team working on Khanmigo.
## Motivation

1. The team working on Khanmigo needed access to Perseus data for prompt engineering - including both external-facing things (like the ItemData and UserInput) and internal things (like RenderProps)
2. The Perseus team didn't want to write a blank check exposing all of our internal data because that would make it difficult for us to safely make internal changes
3. The goal of the helpers in this folder is to have a set of functions that can take _all_ the information the Khanmigo team could possibly want and return only the pieces the Khanmigo team needs

## What are these utilities for?

We want to have a representation of Perseus widgets that LLMs can understand. They understand JSON pretty well! This is a set of utility functions for each widget that get the minimum amount of data for an LLM to understand the state of the widget, as well as the current user input.


### Why don't we just pass the raw widget json?

We do not want to have the an external API relying on the internal
representation of Perseus widgets. That would couple the widgets implementation
to an external API, which would be subject to breakage. This approach balances
having an explicit API, while keeping Perseus widgets mostly unaware of the
LLM prompt requirements.
We do not want to have the external API relying on the internal
representation of Perseus widgets. That would couple the widgets implementation to an external API, which would be subject to breakage. This approach balances having an explicit API, while keeping Perseus widgets mostly unaware of the LLM prompt requirements.
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@ import {testDependencies} from "../../../../../testing/test-dependencies";
import * as Dependencies from "../../dependencies";
import {renderQuestion} from "../../widgets/__testutils__/renderQuestion";

import {getPromptJSON} from "./categorizer-ai-utils";

import type {PerseusRenderer} from "../../perseus-types";
import type {PerseusCategorizerUserInput} from "../../validation.types";
import type {UserEvent} from "@testing-library/user-event";

export const randomizedQuestion: PerseusRenderer = {
const randomizedQuestion: PerseusRenderer = {
content:
"**Classify each graph according to the kind of relationship it suggests.**\n\n$\\qquad\\qquad\\quad\\text{Graph 1}\\qquad\\qquad\\quad\\qquad\\qquad\\quad\\text{Graph 2}$\n\n\n\n[[\u2603 categorizer 1]]\n\n**Graph 1.**\n\n![](https://ka-perseus-graphie.s3.amazonaws.com/049c091ed0978112aba3a36b0591d992baf7b1ac.png)\n\n**Graph 2.**\n\n![](https://ka-perseus-graphie.s3.amazonaws.com/40df186f39fb6d65de6bee0d8b681502d10cb37a.png) \n",
images: {},
Expand All @@ -35,7 +38,7 @@ export const randomizedQuestion: PerseusRenderer = {
},
};

describe("categorizer widget", () => {
describe("Categorizer AI utils", () => {
let userEvent: UserEvent;
beforeEach(() => {
userEvent = userEventLib.setup({
Expand All @@ -47,6 +50,31 @@ describe("categorizer widget", () => {
);
});

it("it returns JSON with the expected format and fields", () => {
const renderProps: any = {
items: ["Luke Skywalker", "Darth Vader", "Yoda", "Han Solo"],
categories: ["Galactic Empire", "Rebel Alliance"],
values: [1, 0, 1, 1],
};

const userInput: PerseusCategorizerUserInput = {
values: [1, 0, 0, 1],
};

const resultJSON = getPromptJSON(renderProps, userInput);

expect(resultJSON).toEqual({
type: "categorizer",
options: {
items: ["Luke Skywalker", "Darth Vader", "Yoda", "Han Solo"],
categories: ["Galactic Empire", "Rebel Alliance"],
},
userInput: {
itemToCategoryMapping: [1, 0, 0, 1],
},
});
});

it("should get prompt json which matches the state of the UI for a randomized question", async () => {
// arrange
const {renderer} = renderQuestion(randomizedQuestion);
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import {renderQuestion} from "../../widgets/__testutils__/renderQuestion";

import {getPromptJSON} from "./cs-program-ai-utils";

import type {PerseusRenderer} from "../../perseus-types";

export const question1: PerseusRenderer = {
const question1: PerseusRenderer = {
content: "[[\u2603 cs-program 1]]\n\n",
images: {},
widgets: {
Expand All @@ -28,7 +30,17 @@ export const question1: PerseusRenderer = {
},
};

describe("cs-program widget", () => {
describe("CS Program AI utils", () => {
it("it returns JSON with the expected format and fields", () => {
const resultJSON = getPromptJSON();

expect(resultJSON).toEqual({
type: "cs-program",
isSupported: false,
message: "",
});
});

it("should get prompt json which matches the state of the UI", async () => {
// Arrange
const {renderer} = renderQuestion(question1, {isMobile: false});
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import {renderQuestion} from "../../widgets/__testutils__/renderQuestion";

import {getPromptJSON} from "./definition-ai-utils";

const question = {
content:
"Read the excerpt and answer the question below. \n\nThe Governor and Council of the Massachusetts had much conference many days; and at last . . . . concluded a peace and friendship with [[\u2603 definition 1]], upon these conditions.",
Expand All @@ -23,7 +25,22 @@ const question = {
},
} as const;

describe("definition widget", () => {
describe("Definition AI utils", () => {
it("it returns JSON with the expected format and fields", () => {
const renderProps: any = {
definition: "to confuse or fluster",
togglePrompt: "bumfuzzle",
};

const resultJSON = getPromptJSON(renderProps);

expect(resultJSON).toEqual({
type: "definition",
definition: "to confuse or fluster",
togglePrompt: "bumfuzzle",
});
});

it("should get prompt json which matches the state of the UI", async () => {
// Arrange
const {renderer} = renderQuestion(question);
Expand Down

This file was deleted.

Loading

0 comments on commit 9c2289b

Please sign in to comment.