Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rename AI files #1860

Merged
merged 28 commits into from
Nov 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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