Some checks failed
App Prod-Parity E2E Dispatch / dispatch (push) Failing after 10s
CD Storybook UI / build (push) Failing after 3m25s
CD Storybook UI / dispatch (push) Has been skipped
CD deploy main / website-changed-files (push) Successful in 18m8s
CI Agent Skills / changed-files-check (push) Successful in 18m9s
CI Create App E2E minimal / changed-files-check (push) Successful in 24s
CI Create App / changed-files-check (push) Successful in 26s
CI Docs / changed-files-check (push) Successful in 26s
CI Emails / changed-files-check (push) Successful in 28s
CI Example App Hello World / changed-files-check (push) Successful in 23s
CI Front / changed-files-check (push) Has been skipped
CI Example App Postcard / changed-files-check (push) Successful in 27s
CI UI / changed-files-check (push) Has been skipped
CI Utils Test / changed-files-check (push) Successful in 45s
CI Twenty Apps / discover (push) Successful in 1m3s
CD deploy main / deploy-main (push) Failing after 3s
CI Agent Skills / agent-skills-validate (push) Has been skipped
CI Create App / create-app-test (lint) (push) Has been skipped
CI Emails / emails-test (push) Has been skipped
CI Front / front-task (lingui:compile) (push) Has been skipped
CI Front / front-task (lint) (push) Has been skipped
CI Example App Postcard / example-app-postcard (push) Has been skipped
CI UI / ui-task (lint) (push) Has been skipped
CI UI / ui-task (pack-size) (push) Has been skipped
CI UI / ui-task (size) (push) Has been skipped
CI UI / ui-task (test) (push) Has been skipped
CI UI / ui-task (typecheck) (push) Has been skipped
CI Utils Test / utils-test (push) Has been skipped
CI Twenty Apps / ${{ matrix.app.name }} (push) Has been skipped
CI Emails / ci-emails-status-check (push) Successful in 2s
CI Example App Hello World / ci-example-app-hello-world-status-check (push) Successful in 2s
CI Example App Postcard / ci-example-app-postcard-status-check (push) Successful in 3s
CI UI / ui-sb-test (push) Has been skipped
CI Utils Test / ci-utils-test-status-check (push) Successful in 2s
CI Twenty Apps / ci-twenty-apps-status-check (push) Successful in 2s
CI UI / ci-ui-status-check (push) Successful in 2s
CI Desktop / desktop (push) Failing after 1m8s
Push docs to Crowdin / Push documentation to Crowdin (push) Failing after 55s
Push translations to Crowdin / Extract and upload translations (push) Failing after 5s
Push website translations to Crowdin / Extract and upload website translations (push) Failing after 5s
CI Create App / create-app-test (test) (push) Has been skipped
CI Create App / create-app-test (typecheck) (push) Has been skipped
CI Docs / docs-lint (push) Has been skipped
CI Example App Hello World / example-app-hello-world (push) Has been skipped
CI Front / front-task (lingui:extract) (push) Has been skipped
CI Front / front-task (test) (push) Has been skipped
CI Front / front-task (typecheck) (push) Has been skipped
CI UI / ui-sb-build (push) Failing after 1m32s
CI Twenty Apps / ${{ matrix.app.name }} (${{ matrix.server-source }}) (push) Has been skipped
CI Agent Skills / agent-skills-publish (push) Has been skipped
CI Create App / ci-create-app-status-check (push) Successful in 2s
CI Agent Skills / agent-skills-remote-source (push) Has been skipped
CI Create App E2E minimal / create-app-e2e-minimal (push) Has been cancelled
CI E2E Main / e2e-test (push) Has been cancelled
CI Front / front-sb-build (push) Has been cancelled
CI Front / front-build (push) Has been cancelled
CI Create App E2E minimal / ci-create-app-e2e-minimal-status-check (push) Has been cancelled
CI E2E Main / ci-e2e-main-status-check (push) Has been cancelled
CI E2E Main / notify-main-ci-failure (push) Has been cancelled
CI E2E Main / qa-scout-comment (push) Has been cancelled
CI Front / front-sb-test (push) Has been cancelled
CI Front / front-sb-screenshots (push) Has been cancelled
CI Front / ci-front-status-check (push) Has been cancelled
DPA Sub-Processor Sync / sync-subprocessors (push) Failing after 3s
AI Catalog Sync / sync-catalog (push) Failing after 2s
70 lines
2.4 KiB
TypeScript
70 lines
2.4 KiB
TypeScript
import { isDefined } from 'twenty-shared/utils';
|
|
|
|
import { type ModelsDevModel } from 'src/engine/metadata-modules/ai/ai-models/types/models-dev-model.type';
|
|
|
|
const DATE_SUFFIX = /-\d{4}-?\d{2}-?\d{2}$/;
|
|
const ROLLING_SUFFIX = /-(latest|preview|exp)$/;
|
|
|
|
const fingerprint = (model: ModelsDevModel): string =>
|
|
JSON.stringify([model.cost ?? {}, model.limit ?? {}]);
|
|
|
|
// `mistral-large-latest` is never benchmarked under that name, so it is
|
|
// resolved to the dated release it currently points at by matching price and
|
|
// limits against its non-rolling siblings. Re-resolves on its own when the
|
|
// provider repoints the alias.
|
|
const resolveRollingAlias = (
|
|
modelName: string,
|
|
siblingModels: Record<string, ModelsDevModel>,
|
|
): string | undefined => {
|
|
const model = siblingModels[modelName];
|
|
|
|
if (!isDefined(model) || !ROLLING_SUFFIX.test(modelName)) {
|
|
return undefined;
|
|
}
|
|
|
|
const target = fingerprint(model);
|
|
|
|
const twins = Object.entries(siblingModels)
|
|
.filter(
|
|
([siblingName, sibling]) =>
|
|
siblingName !== modelName &&
|
|
!ROLLING_SUFFIX.test(siblingName) &&
|
|
fingerprint(sibling) === target,
|
|
)
|
|
// Falling back to the name keeps this deterministic when a provider dates
|
|
// neither twin, and for the date-stamped ids providers actually use it
|
|
// still lands on the newer one.
|
|
.sort(
|
|
([nameA, a], [nameB, b]) =>
|
|
(b.release_date ?? '').localeCompare(a.release_date ?? '') ||
|
|
nameB.localeCompare(nameA),
|
|
);
|
|
|
|
return twins[0]?.[0];
|
|
};
|
|
|
|
export const buildLookupCandidates = ({
|
|
modelName,
|
|
siblingModels,
|
|
}: {
|
|
modelName: string;
|
|
siblingModels: Record<string, ModelsDevModel>;
|
|
}): string[] => {
|
|
const candidates = [modelName, modelName.replace(DATE_SUFFIX, '')];
|
|
|
|
const resolved = resolveRollingAlias(modelName, siblingModels);
|
|
|
|
if (isDefined(resolved)) {
|
|
// Once the release an alias points at is known, only a row naming that
|
|
// release will do. Every undated spelling is some other release the
|
|
// publisher happens to have measured: `mistral-large` on the leaderboard is
|
|
// the Feb '24 model, and standing in for `mistral-large-2512` it published a
|
|
// two-year-old score as current.
|
|
return [...new Set([...candidates, resolved])];
|
|
}
|
|
|
|
// No dated release to point at, so the bare name is the only thing left and
|
|
// whichever release the publisher measured is the best answer available.
|
|
return [...new Set([...candidates, modelName.replace(ROLLING_SUFFIX, '')])];
|
|
};
|