Skip to content
This repository has been archived by the owner on Jun 2, 2024. It is now read-only.

[lib] Fix cumulative metrics [web] Implement migrations #33

Merged
merged 6 commits into from
Jul 7, 2023
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
4 changes: 2 additions & 2 deletions packages/lib/src/classes/Conversation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -655,7 +655,7 @@ export class Conversation {

const unsubscribeStreaming = message.onMessageStreamingStop((m) => {
// FIXME: Find out how the size is calculated for messages with function calls, fix in Message class and remove this condition
if (message.isFunctionCall()) {
if (!message.isFunctionCall()) {
this.cumulativeSize += this.getSize() + m.size;
this.cumulativeCost += this.getCost() + m.cost;
}
Expand Down Expand Up @@ -736,7 +736,7 @@ export class Conversation {
}

// FIXME: Find out how the size is calculated for messages with function calls, fix in Message class and remove this condition
if (message.isFunctionCall()) {
if (!message.isFunctionCall()) {
this.cumulativeSize += this.getSize() + message.size;
this.cumulativeCost += this.getCost() + message.cost;
}
Expand Down
9 changes: 6 additions & 3 deletions packages/web/src/components/SettingsFormModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,17 @@ const SettingsFormModal = ({
const theme = useMantineTheme();
const isSm = useMediaQuery(`(max-width: ${theme.breakpoints.md})`);

const { setSettings } = useSettings();
const { settings, setSettings } = useSettings();

const onSubmit = React.useCallback(
(values: ConversationFormValues) => {
setSettings(values);
setSettings({
...settings,
...values,
});
onClose();
},
[onClose, setSettings]
[onClose, setSettings, settings]
);

return (
Expand Down
3 changes: 3 additions & 0 deletions packages/web/src/config/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,6 @@ export const CODE_LANGUAGES = [
] as const;

export const DISCORD_SERVER_INVITE = "https://discord.gg/Aa77KCmwRx";

export const STORAGEKEY_PERSISTENCE = "gpt-turbo-persistence";
export const STORAGEKEY_SETTINGS = "gpt-turbo-settings";
2 changes: 2 additions & 0 deletions packages/web/src/contexts/PersistenceContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import makeNotImplemented from "../utils/makeNotImplemented";
import { Persistence } from "../entities/persistence";
import { PersistenceContext as PersistenceContextEntity } from "../entities/persistenceContext";
import { PersistencePrompt } from "../entities/persistencePrompt";
import { persistenceVersion } from "../entities/migrations/persistence";

export interface PersistenceContextValue {
persistence: Persistence;
Expand All @@ -18,6 +19,7 @@ export interface PersistenceContextValue {
const notImplemented = makeNotImplemented("PersistenceContext");
export const PersistenceContext = React.createContext<PersistenceContextValue>({
persistence: {
version: persistenceVersion,
conversations: [],
contexts: [],
prompts: [],
Expand Down
2 changes: 2 additions & 0 deletions packages/web/src/contexts/SettingsContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
import React from "react";
import makeNotImplemented from "../utils/makeNotImplemented";
import { Settings } from "../entities/settings";
import { settingsVersion } from "../entities/migrations/settings";

export interface SettingsContextValue {
settings: Settings;
Expand All @@ -17,6 +18,7 @@ export interface SettingsContextValue {
const notImplemented = makeNotImplemented("SettingsContext");
export const SettingsContext = React.createContext<SettingsContextValue>({
settings: {
version: settingsVersion,
save: false,

apiKey: "",
Expand Down
5 changes: 4 additions & 1 deletion packages/web/src/contexts/providers/PersistenceProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import { PersistenceConversation } from "../../entities/persistenceConversation"
import { Conversation, Message } from "gpt-turbo";
import useCallableFunctions from "../../hooks/useCallableFunctions";
import { PersistenceCallableFunction } from "../../entities/persistenceCallableFunction";
import { STORAGEKEY_PERSISTENCE } from "../../config/constants";
import { persistenceVersion } from "../../entities/migrations/persistence";

interface PersistenceProviderProps {
children?: React.ReactNode;
Expand Down Expand Up @@ -39,8 +41,9 @@ const PersistenceProvider = ({ children }: PersistenceProviderProps) => {

const { value: persistence, setValue: setPersistence } =
useStorage<Persistence>(
"gpt-turbo-persistence",
STORAGEKEY_PERSISTENCE,
{
version: persistenceVersion,
conversations: [],
contexts: [],
prompts: [],
Expand Down
22 changes: 20 additions & 2 deletions packages/web/src/contexts/providers/SettingsProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,33 @@ import React from "react";
import { SettingsContext, SettingsContextValue } from "../SettingsContext";
import useStorage from "../../hooks/useStorage";
import { Settings, settingsSchema } from "../../entities/settings";
import { STORAGEKEY_SETTINGS } from "../../config/constants";
import {
DEFAULT_CONTEXT,
DEFAULT_DISABLEMODERATION,
DEFAULT_DRY,
DEFAULT_MODEL,
} from "gpt-turbo";
import { settingsVersion } from "../../entities/migrations/settings";

interface SettingsProviderProps {
children?: React.ReactNode;
}

const SettingsProvider = ({ children }: SettingsProviderProps) => {
const { value: settings, setValue: setSettings } = useStorage<Settings>(
"gpt-turbo-settings",
settingsSchema.parse({}),
STORAGEKEY_SETTINGS,
{
apiKey: "",
context: DEFAULT_CONTEXT,
disableModeration: DEFAULT_DISABLEMODERATION,
dry: DEFAULT_DRY,
functionIds: [],
model: DEFAULT_MODEL,
save: false,
stream: true,
version: settingsVersion,
},
settingsSchema
);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export const migratePersistenceInitial = (
value: Record<string, any>
): Record<string, any> => {
// Applies the initial migration to add the version key
return value;
};
18 changes: 18 additions & 0 deletions packages/web/src/entities/migrations/persistence/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { migratePersistenceInitial } from "./1688489405401_initial";

const migrations: ((value: Record<string, any>) => Record<string, any>)[] = [
migratePersistenceInitial,
];

export const persistenceVersion = migrations.length;

export const migratePersistence = (value: Record<string, any>) =>
migrations.reduce((acc, migration, i) => {
const version = i + 1;

if ((acc.version ?? 0) >= version) return acc;
return {
...migration(acc),
version,
};
}, value);
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export const migrateSettingsInitial = (
value: Record<string, any>
): Record<string, any> => {
// Applies the initial migration to add the version key
return value;
};
18 changes: 18 additions & 0 deletions packages/web/src/entities/migrations/settings/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { migrateSettingsInitial } from "./1688489405401_initial";

const migrations: ((value: Record<string, any>) => Record<string, any>)[] = [
migrateSettingsInitial,
];

export const settingsVersion = migrations.length;

export const migrateSettings = (value: Record<string, any>) =>
migrations.reduce((acc, migration, i) => {
const version = i + 1;

if ((acc.version ?? 0) >= version) return acc;
return {
...migration(acc),
version,
};
}, value);
1 change: 1 addition & 0 deletions packages/web/src/entities/persistence.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { persistencePromptSchema } from "./persistencePrompt";
import { persistenceCallableFunctionSchema } from "./persistenceCallableFunction";

export const persistenceSchema = z.object({
version: z.number(),
conversations: z.array(persistenceConversationSchema),
contexts: z.array(persistenceContextSchema).refine((contexts) => {
const names = contexts.map((c) => c.name.toLowerCase());
Expand Down
2 changes: 2 additions & 0 deletions packages/web/src/entities/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import {
import { z } from "zod";

export const settingsSchema = z.object({
version: z.number(),

save: z.boolean().default(false),

apiKey: conversationConfigSchema.shape.apiKey.default(""),
Expand Down
29 changes: 20 additions & 9 deletions packages/web/src/hooks/useStorage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@ import { Button, Stack, Text } from "@mantine/core";
import { useLocalStorage } from "@mantine/hooks";
import { notifications } from "@mantine/notifications";
import { ZodError, ZodType } from "zod";
import {
STORAGEKEY_PERSISTENCE,
STORAGEKEY_SETTINGS,
} from "../config/constants";
import { migratePersistence } from "../entities/migrations/persistence";
import { migrateSettings } from "../entities/migrations/settings";

const warns = new Set<string>();

Expand Down Expand Up @@ -61,6 +67,16 @@ const repairValueFromZodError = <T,>(
);
};

const getMigratedValue = (key: string, value: any) => {
switch (key) {
case STORAGEKEY_PERSISTENCE:
return migratePersistence(value);
case STORAGEKEY_SETTINGS:
return migrateSettings(value);
}
return value;
};

const useStorage = <T,>(
key: string,
defaultValue: T,
Expand All @@ -70,16 +86,11 @@ const useStorage = <T,>(
key: key,
defaultValue,
getInitialValueInEffect: false,
serialize: (value) =>
JSON.stringify(
(() => {
if (value === undefined) return defaultValue;
if (schema) return schema.parse(value);
return value;
})()
),
serialize: (value) => {
return JSON.stringify(schema?.parse(value) ?? value);
},
deserialize: (v) => {
const value = JSON.parse(v);
const value = getMigratedValue(key, JSON.parse(v));
if (!schema) return value;

const result = schema.safeParse(value);
Expand Down
Loading