Compare commits

..
23 Commits
Author SHA1 Message Date
Max Deichmann a829447410 chore: release v2.2.0
CI/CD / lint (push) Waiting to run
CI/CD / test-docker-build (push) Waiting to run
CI/CD / tests (18) (push) Waiting to run
CI/CD / tests (20) (push) Waiting to run
CI/CD / e2e-tests (push) Waiting to run
CI/CD / all-ci-passed (push) Blocked by required conditions
CI/CD / push-docker-image (push) Blocked by required conditions
release.yml / release (push) Waiting to run
2024-02-07 11:06:35 +01:00
Hassieb PakzadandGitHub 53e7ff4e16 feat: expand generation model units (#1095) 2024-02-07 11:05:07 +01:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
4a85b4a4f2 chore(deps): bump the patches group with 3 updates (#1101)
Bumps the patches group with 3 updates: [posthog-node](https://github.com/PostHog/posthog-js-lite/tree/HEAD/posthog-node), [react-hook-form](https://github.com/react-hook-form/react-hook-form) and [@types/react](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react).


Updates `posthog-node` from 3.6.1 to 3.6.2
- [Release notes](https://github.com/PostHog/posthog-js-lite/releases)
- [Changelog](https://github.com/PostHog/posthog-js-lite/blob/main/posthog-node/CHANGELOG.md)
- [Commits](https://github.com/PostHog/posthog-js-lite/commits/posthog-node-v3.6.2/posthog-node)

Updates `react-hook-form` from 7.50.0 to 7.50.1
- [Release notes](https://github.com/react-hook-form/react-hook-form/releases)
- [Changelog](https://github.com/react-hook-form/react-hook-form/blob/master/CHANGELOG.md)
- [Commits](https://github.com/react-hook-form/react-hook-form/compare/v7.50.0...v7.50.1)

Updates `@types/react` from 18.2.54 to 18.2.55
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react)

---
updated-dependencies:
- dependency-name: posthog-node
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patches
- dependency-name: react-hook-form
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patches
- dependency-name: "@types/react"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: patches
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-07 03:16:05 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
d2e6dca3d3 chore(deps-dev): bump @typescript-eslint/parser from 6.20.0 to 6.21.0 (#1103)
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 6.20.0 to 6.21.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v6.21.0/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/parser"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-07 03:08:08 +00:00
Marc KlingenandGitHub cdbdc0af67 feat(api): add notice regarding hostname to default 401 (#1088) 2024-02-07 04:02:26 +01:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2af9b52213 chore(deps): bump @aws-sdk/s3-request-presigner from 3.504.0 to 3.507.0 (#1104)
Bumps [@aws-sdk/s3-request-presigner](https://github.com/aws/aws-sdk-js-v3/tree/HEAD/packages/s3-request-presigner) from 3.504.0 to 3.507.0.
- [Release notes](https://github.com/aws/aws-sdk-js-v3/releases)
- [Changelog](https://github.com/aws/aws-sdk-js-v3/blob/main/packages/s3-request-presigner/CHANGELOG.md)
- [Commits](https://github.com/aws/aws-sdk-js-v3/commits/v3.507.0/packages/s3-request-presigner)

---
updated-dependencies:
- dependency-name: "@aws-sdk/s3-request-presigner"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-07 04:01:08 +01:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
894a3d1b32 chore(deps-dev): bump the patches group with 4 updates (#1083)
Bumps the patches group with 4 updates: [@testing-library/jest-dom](https://github.com/testing-library/jest-dom), [@types/react](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react), [postcss](https://github.com/postcss/postcss) and [prettier](https://github.com/prettier/prettier).


Updates `@testing-library/jest-dom` from 6.4.1 to 6.4.2
- [Release notes](https://github.com/testing-library/jest-dom/releases)
- [Changelog](https://github.com/testing-library/jest-dom/blob/main/CHANGELOG.md)
- [Commits](https://github.com/testing-library/jest-dom/compare/v6.4.1...v6.4.2)

Updates `@types/react` from 18.2.51 to 18.2.54
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react)

Updates `postcss` from 8.4.33 to 8.4.34
- [Release notes](https://github.com/postcss/postcss/releases)
- [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/postcss/postcss/compare/8.4.33...8.4.34)

Updates `prettier` from 3.2.4 to 3.2.5
- [Release notes](https://github.com/prettier/prettier/releases)
- [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/prettier/compare/3.2.4...3.2.5)

---
updated-dependencies:
- dependency-name: "@testing-library/jest-dom"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: patches
- dependency-name: "@types/react"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: patches
- dependency-name: postcss
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: patches
- dependency-name: prettier
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: patches
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-06 02:53:42 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
82f0134368 chore(deps): bump react-hook-form from 7.49.3 to 7.50.0 (#1084)
Bumps [react-hook-form](https://github.com/react-hook-form/react-hook-form) from 7.49.3 to 7.50.0.
- [Release notes](https://github.com/react-hook-form/react-hook-form/releases)
- [Changelog](https://github.com/react-hook-form/react-hook-form/blob/master/CHANGELOG.md)
- [Commits](https://github.com/react-hook-form/react-hook-form/compare/v7.49.3...v7.50.0)

---
updated-dependencies:
- dependency-name: react-hook-form
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-06 02:41:56 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
e52ba46b0e chore(deps): bump lucide-react from 0.321.0 to 0.323.0 (#1085)
Bumps [lucide-react](https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react) from 0.321.0 to 0.323.0.
- [Release notes](https://github.com/lucide-icons/lucide/releases)
- [Commits](https://github.com/lucide-icons/lucide/commits/0.323.0/packages/lucide-react)

---
updated-dependencies:
- dependency-name: lucide-react
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-06 02:37:21 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
6aca4954ef chore(deps): bump @aws-sdk/client-s3 from 3.504.0 to 3.507.0 (#1086)
Bumps [@aws-sdk/client-s3](https://github.com/aws/aws-sdk-js-v3/tree/HEAD/clients/client-s3) from 3.504.0 to 3.507.0.
- [Release notes](https://github.com/aws/aws-sdk-js-v3/releases)
- [Changelog](https://github.com/aws/aws-sdk-js-v3/blob/main/clients/client-s3/CHANGELOG.md)
- [Commits](https://github.com/aws/aws-sdk-js-v3/commits/v3.507.0/clients/client-s3)

---
updated-dependencies:
- dependency-name: "@aws-sdk/client-s3"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-06 03:32:53 +01:00
Marc Klingen 9d5fa4e2f1 chore: fix discussion template 2024-02-05 10:51:50 +01:00
Marc Klingen c1db242edd chore: fix discussion template 2024-02-05 10:51:21 +01:00
Marc Klingen 91a2c63c88 chore: fix discussion template 2024-02-05 10:50:25 +01:00
Marc Klingen f7d9bd7297 chore: add template for gh discussions 2024-02-05 10:49:16 +01:00
Max DeichmannandGitHub d94e880520 fix: openai model prices (#1068) 2024-02-03 18:28:18 +01:00
Yash KhareandGitHub 74e9053f85 feat(dashboard): enable selection of score names in legend of chart + slider (#907) 2024-02-03 01:53:44 +00:00
Marc Klingen ae5260d808 docs: update example envs 2024-02-03 02:29:50 +01:00
Marc KlingenandGitHub f72f8b7e2c chore(deps): upgrade prisma and fix tests (#1064) 2024-02-03 01:34:05 +01:00
Marc Klingen 43108eccde docs: readme 2024-02-03 01:16:34 +01:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
c93c9560e1 chore(deps): bump the patches group with 1 update (#1060)
Bumps the patches group with 1 update: [@tanstack/react-table](https://github.com/TanStack/table/tree/HEAD/packages/react-table).


Updates `@tanstack/react-table` from 8.11.7 to 8.11.8
- [Release notes](https://github.com/TanStack/table/releases)
- [Commits](https://github.com/TanStack/table/commits/v8.11.8/packages/react-table)

---
updated-dependencies:
- dependency-name: "@tanstack/react-table"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patches
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-02 23:31:07 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
ddad1afd7b chore(deps): bump @aws-sdk/client-s3 from 3.501.0 to 3.504.0 (#1061)
Bumps [@aws-sdk/client-s3](https://github.com/aws/aws-sdk-js-v3/tree/HEAD/clients/client-s3) from 3.501.0 to 3.504.0.
- [Release notes](https://github.com/aws/aws-sdk-js-v3/releases)
- [Changelog](https://github.com/aws/aws-sdk-js-v3/blob/main/clients/client-s3/CHANGELOG.md)
- [Commits](https://github.com/aws/aws-sdk-js-v3/commits/v3.504.0/clients/client-s3)

---
updated-dependencies:
- dependency-name: "@aws-sdk/client-s3"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-02 23:21:19 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2b70ae3742 chore(deps): bump @aws-sdk/s3-request-presigner from 3.501.0 to 3.504.0 (#1063)
Bumps [@aws-sdk/s3-request-presigner](https://github.com/aws/aws-sdk-js-v3/tree/HEAD/packages/s3-request-presigner) from 3.501.0 to 3.504.0.
- [Release notes](https://github.com/aws/aws-sdk-js-v3/releases)
- [Changelog](https://github.com/aws/aws-sdk-js-v3/blob/main/packages/s3-request-presigner/CHANGELOG.md)
- [Commits](https://github.com/aws/aws-sdk-js-v3/commits/v3.504.0/packages/s3-request-presigner)

---
updated-dependencies:
- dependency-name: "@aws-sdk/s3-request-presigner"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-02 23:16:52 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
b110fd7932 chore(deps): bump posthog-js from 1.103.1 to 1.104.4 (#1062)
Bumps [posthog-js](https://github.com/PostHog/posthog-js) from 1.103.1 to 1.104.4.
- [Release notes](https://github.com/PostHog/posthog-js/releases)
- [Changelog](https://github.com/PostHog/posthog-js/blob/main/CHANGELOG.md)
- [Commits](https://github.com/PostHog/posthog-js/compare/v1.103.1...v1.104.4)

---
updated-dependencies:
- dependency-name: posthog-js
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-03 00:12:21 +01:00
31 changed files with 766 additions and 462 deletions
+9
View File
@@ -16,8 +16,17 @@ NEXTAUTH_SECRET="secret"
# Langfuse experimental features
LANGFUSE_ENABLE_EXPERIMENTAL_FEATURES="true"
# Salt for API key hashing
SALT="salt"
# Email
EMAIL_FROM_ADDRESS="" # Defines the email address to use as the from address.
SMTP_CONNECTION_URL="" # Defines the connection url for smtp server.
# S3 storage
S3_ENDPOINT=
S3_ACCESS_KEY_ID=
S3_SECRET_ACCESS_KEY=
S3_BUCKET_NAME=
S3_REGION=
+1 -8
View File
@@ -1,21 +1,14 @@
# When adding additional environment variables, the schema in "/src/env.mjs"
# should be updated accordingly.
# Prisma
# https://www.prisma.io/docs/reference/database-reference/connection-urls#env
DIRECT_URL="postgresql://postgres:postgres@db:5432/postgres"
DATABASE_URL="postgresql://postgres:postgres@db:5432/postgres"
# Next Auth
# You can generate a new secret on the command line with:
# openssl rand -base64 32
# https://next-auth.js.org/configuration/options#secret
NEXTAUTH_SECRET="secret"
NEXTAUTH_URL="http://localhost:3000"
# feature flag to enable experimental features locally
LANGFUSE_ENABLE_EXPERIMENTAL_FEATURES="false"
SALT="salt"
# Email
EMAIL_FROM_ADDRESS="" # Defines the email address to use as the from address.
SMTP_CONNECTION_URL="" # Defines the connection url for smtp server.
+66 -34
View File
@@ -1,32 +1,72 @@
# Assuming deployment on Vercel with Postgres database on Supabase
NEXT_PUBLIC_LANGFUSE_CLOUD_REGION="US"
NEXTAUTH_COOKIE_DOMAIN=".langfuse.com"
# More information: https://langfuse.com/docs/deployment/self-host
# When adding additional environment variables, the schema in "/src/env.mjs"
# should be updated accordingly.
# Prisma
# https://www.prisma.io/docs/reference/database-reference/connection-urls#env
DIRECT_URL="postgresql://postgres:[pw]@db.[db_id].supabase.co:5432/postgres"
DATABASE_URL="postgres://postgres:[pw]@db.[db_id].supabase.co:6543/postgres?pgbouncer=true&connection_limit=1"
# DATABASE_URL supports pooled connections, but then you need to set DIRECT_URL
DATABASE_URL="postgresql://postgres:postgres@db:5432/postgres"
# DIRECT_URL="postgresql://postgres:postgres@db:5432/postgres"
# SHADOW_DATABASE_URL=
# Next Auth
# NEXTAUTH_URL does not need to be set when deploying on Vercel
# NEXTAUTH_URL="http://localhost:3000"
# AUTH_REDIRECT_PROXY_URL used to proxy oauth callbacks on e.g. preview deployments. optional.
# AUTH_REDIRECT_PROXY_URL="https://example.com/api/auth"
NEXTAUTH_URL="http://localhost:3000"
# You can generate a new secret on the command line with:
# openssl rand -base64 32
# https://next-auth.js.org/configuration/options#secret
NEXTAUTH_SECRET="secret"
SALT="salt"
# Sentry; set via Vercel integration
# NEXT_PUBLIC_SENTRY_DSN=
# NEXT_SENTRY_ORG=
# NEXT_SENTRY_PROJECT=
# SENTRY_AUTH_TOKEN=
# Docker only, optional
# PORT=3000
# HOSTNAME=localhost
# Default project, optional
# LANGFUSE_DEFAULT_PROJECT_ID=
# LANGFUSE_DEFAULT_PROJECT_ROLE=
# Enable experimental features, optional
# NEXT_PUBLIC_ENABLE_EXPERIMENTAL_FEATURES
# Auth, optional configuration
# AUTH_DOMAINS_WITH_SSO_ENFORCEMENT=domain1.com,domain2.com
# AUTH_DISABLE_USERNAME_PASSWORD=true
# SSO, each group is optional
# AUTH_GOOGLE_CLIENT_ID=
# AUTH_GOOGLE_CLIENT_SECRET=
# AUTH_GITHUB_CLIENT_ID=
# AUTH_GITHUB_CLIENT_SECRET=
# AUTH_AZURE_AD_CLIENT_ID=
# AUTH_AZURE_AD_CLIENT_SECRET=
# AUTH_AZURE_AD_TENANT_ID=
# Transactional email, optional
# Defines the email address to use as the from address.
# EMAIL_FROM_ADDRESS=
# Defines the connection url for smtp server.
# SMTP_CONNECTION_URL=
# S3 storage, optional, used for exports from the UI
# S3_ENDPOINT=
# S3_ACCESS_KEY_ID=
# S3_SECRET_ACCESS_KEY=
# S3_BUCKET_NAME=
# S3_REGION=
### START Langfuse Cloud Config
# Used for Langfuse Cloud deployments
# Not recommended for self-hosted deployments as these are NOT COVERED BY SEMVER
# NEXT_PUBLIC_LANGFUSE_CLOUD_REGION="US"
# NEXTAUTH_COOKIE_DOMAIN=".langfuse.com"
# LANGFUSE_TEAM_SLACK_WEBHOOK=
# LANGFUSE_NEW_USER_SIGNUP_WEBHOOK=
@@ -35,24 +75,16 @@ SALT="salt"
# NEXT_PUBLIC_POSTHOG_HOST=
# NEXT_PUBLIC_POSTHOG_KEY=
# Id of demo project to automatically assign new users to
# Sentry
# NEXT_PUBLIC_SENTRY_DSN=
# NEXT_SENTRY_ORG=
# NEXT_SENTRY_PROJECT=
# SENTRY_AUTH_TOKEN=
# Demo project that users can use to try the platform
# NEXT_PUBLIC_DEMO_PROJECT_ID=
# Auth, each group is optional
AUTH_GOOGLE_CLIENT_ID=
AUTH_GOOGLE_CLIENT_SECRET=
AUTH_GITHUB_CLIENT_ID=
AUTH_GITHUB_CLIENT_SECRET=
# AUTH_DOMAINS_WITH_SSO_ENFORCEMENT=domain1.com,domain2.com
# AUTH_DISABLE_USERNAME_PASSWORD=true
# Crisp chat
# NEXT_PUBLIC_CRISP_WEBSITE_ID=
# Email
EMAIL_FROM_ADDRESS="" # Defines the email address to use as the from address.
SMTP_CONNECTION_URL="" # Defines the connection url for smtp server.
# S3 storage (eg for exports), necessary for serverless deployments
S3_ENDPOINT=""
S3_ACCESS_KEY_ID=""
S3_SECRET_ACCESS_KEY=""
S3_BUCKET_NAME=""
S3_REGION=""
### END Langfuse Cloud Config
+18
View File
@@ -0,0 +1,18 @@
body:
- type: textarea
attributes:
label: Describe the feature or potential improvement
description: Please describe the change as clear and concise as possible. Remember to add context as to why you believe this is needed.
validations:
required: true
- type: textarea
attributes:
label: Additional information
description: Add any other information related to the change here. If your idea is related to any issues or discussions, link them here.
- type: checkboxes
id: contribute
attributes:
label: Contribute
description: Are you willing to contribute to the implementation of this idea?
options:
- label: Yes, I can implement this and raise a PR
+10 -1
View File
@@ -13,6 +13,14 @@
</div>
</br>
<div>
<a href="https://cloud.langfuse.com">
<strong>Langfuse Cloud »</strong>
</a>
</br>
<a href="https://langfuse.com/docs/deployment/self-host">
<strong>Self Host Langfuse »</strong>
</a>
</br>
<a href="https://discord.gg/7NXusRtqYU">
<strong>Join the Langfuse Discord »</strong>
</a>
@@ -26,11 +34,12 @@
<a href="https://github.com/langfuse/langfuse/issues/new?labels=%F0%9F%90%9E%E2%9D%94+unconfirmed+bug&projects=&template=bug_report.yml&title=bug%3A+">
<strong>Report Bug</strong>
</a> ·
<a href="https://github.com/langfuse/langfuse/issues/new?assignees=&labels=%E2%9C%A8+enhancement&projects=&template=feature_request.yml&title=feat%3A+">
<a href="https://github.com/orgs/langfuse/discussions/new?category=ideas">
<strong>Feature Request</strong>
</a>
</div>
</br>
</br>
<div>
<img src="https://img.shields.io/badge/License-MIT-red.svg?style=flat-square" alt="MIT License">
<a href="https://discord.gg/7NXusRtqYU"><img src="https://img.shields.io/discord/1111061815649124414?style=flat-square&logo=Discord&logoColor=white&label=Discord&color=%23434EE4" alt="Discord"></a>
+3
View File
@@ -132,6 +132,9 @@ types:
enum:
- CHARACTERS
- TOKENS
- MILLISECONDS
- SECONDS
- IMAGES
ObservationLevel:
enum:
- DEBUG
+3
View File
@@ -1311,6 +1311,9 @@ components:
enum:
- CHARACTERS
- TOKENS
- MILLISECONDS
- SECONDS
- IMAGES
ObservationLevel:
title: ObservationLevel
type: string
+433 -290
View File
File diff suppressed because it is too large Load Diff
+17 -15
View File
@@ -1,6 +1,6 @@
{
"name": "langfuse-core",
"version": "2.1.2",
"version": "2.2.0",
"private": true,
"scripts": {
"prebuild": "cp generated/openapi-client/openapi.yml public/openapi-client.yml && cp generated/openapi-server/openapi.yml public/openapi-server.yml",
@@ -16,6 +16,8 @@
"test": "jest --runInBand",
"test:watch": "jest --watch --runInBand",
"test:e2e": "playwright test",
"infra:dev:up": "docker-compose -f docker-compose.dev.yml up -d",
"infra:dev:down": "docker-compose -f docker-compose.dev.yml down",
"db:migrate": "DISABLE_ERD=false npx prisma migrate dev",
"db:reset": "npx prisma migrate reset",
"db:seed": "npx prisma db seed",
@@ -28,13 +30,13 @@
},
"dependencies": {
"@anthropic-ai/tokenizer": "^0.0.4",
"@aws-sdk/client-s3": "^3.501.0",
"@aws-sdk/s3-request-presigner": "^3.501.0",
"@aws-sdk/client-s3": "^3.507.0",
"@aws-sdk/s3-request-presigner": "^3.507.0",
"@headlessui/react": "^1.7.18",
"@heroicons/react": "^2.1.1",
"@hookform/resolvers": "^3.3.4",
"@next-auth/prisma-adapter": "^1.0.7",
"@prisma/client": "^5.8.1",
"@prisma/client": "^5.9.1",
"@radix-ui/react-accordion": "^1.1.2",
"@radix-ui/react-alert-dialog": "^1.0.5",
"@radix-ui/react-avatar": "^1.0.4",
@@ -63,7 +65,7 @@
"@t3-oss/env-nextjs": "^0.8.0",
"@tailwindcss/forms": "^0.5.7",
"@tanstack/react-query": "^4.36.1",
"@tanstack/react-table": "^8.11.7",
"@tanstack/react-table": "^8.11.8",
"@tremor/react": "^3.11.1",
"@trpc/client": "^10.45.0",
"@trpc/next": "^10.45.0",
@@ -81,17 +83,17 @@
"exponential-backoff": "^3.1.1",
"js-tiktoken": "^1.0.10",
"lodash": "^4.17.21",
"lucide-react": "^0.321.0",
"lucide-react": "^0.323.0",
"next": "^14.1.0",
"next-auth": "^4.24.5",
"next-query-params": "^5.0.0",
"nodemailer": "^6.9.9",
"posthog-js": "^1.103.1",
"posthog-node": "^3.6.1",
"posthog-js": "^1.104.4",
"posthog-node": "^3.6.2",
"react": "18.2.0",
"react-day-picker": "^8.10.0",
"react-dom": "18.2.0",
"react-hook-form": "^7.49.3",
"react-hook-form": "^7.50.1",
"react-icons": "^5.0.1",
"react-responsive": "^9.0.2",
"react18-json-view": "^0.2.7",
@@ -107,7 +109,7 @@
"@mermaid-js/mermaid-cli": "^10.7.0",
"@playwright/test": "^1.41.2",
"@release-it/bumper": "^6.0.1",
"@testing-library/jest-dom": "^6.4.1",
"@testing-library/jest-dom": "^6.4.2",
"@testing-library/react": "^14.2.1",
"@types/bcryptjs": "^2.4.6",
"@types/cors": "^2.8.17",
@@ -116,21 +118,21 @@
"@types/lodash": "^4.14.202",
"@types/node": "20.10.5",
"@types/nodemailer": "^6.4.14",
"@types/react": "^18.2.51",
"@types/react": "^18.2.55",
"@types/react-dom": "^18.2.18",
"@types/uuid": "^9.0.8",
"@typescript-eslint/eslint-plugin": "^6.20.0",
"@typescript-eslint/parser": "^6.20.0",
"@typescript-eslint/parser": "^6.21.0",
"autoprefixer": "^10.4.17",
"dotenv-cli": "^7.3.0",
"eslint": "^8.56.0",
"eslint-config-next": "^14.1.0",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
"postcss": "^8.4.33",
"prettier": "^3.2.4",
"postcss": "^8.4.34",
"prettier": "^3.2.5",
"prettier-plugin-tailwindcss": "^0.5.11",
"prisma": "^5.8.1",
"prisma": "^5.9.1",
"prisma-erd-generator": "^1.11.2",
"release-it": "^17.0.3",
"tailwindcss": "^3.4.1",
@@ -0,0 +1,27 @@
-- This is an empty migration.
DELETE FROM models
WHERE id in ('clrkwk4cb000308l5go4b6otm', 'clrntjt89000a08jw0gcdbd5a');
INSERT INTO models (
id,
project_id,
model_name,
match_pattern,
start_date,
input_price,
output_price,
total_price,
unit,
tokenizer_id,
tokenizer_config
)
VALUES
-- https://openai.com/blog/new-embedding-models-and-api-updates
-- fix prices
('clrkwk4cb000308l5go4b6otm', NULL, 'gpt-3.5-turbo-16k', '(?i)^(gpt-)(35|3.5)(-turbo-16k)$', NULL, 0.000003, 0.000004, NULL, 'TOKENS', 'openai', '{ "tokensPerMessage": 3, "tokensPerName": 1, "tokenizerModel": "gpt-3.5-turbo-16k" }'),
('clrntjt89000a08jw0gcdbd5a', NULL, 'gpt-3.5-turbo-16k-0613', '(?i)^(gpt-)(35|3.5)(-turbo-16k-0613)$', NULL, 0.000003, 0.000004, NULL, 'TOKENS', 'openai', '{ "tokensPerMessage": 3, "tokensPerName": 1, "tokenizerModel": "gpt-3.5-turbo-16k-0613" }')
+1 -1
View File
@@ -440,7 +440,7 @@ model Model {
inputPrice Decimal? @map("input_price")
outputPrice Decimal? @map("output_price")
totalPrice Decimal? @map("total_price")
unit String // TOKENS or CHARACTERS
unit String // TOKENS, CHARACTERS, MILLISECONDS, SECONDS, or IMAGES
tokenizerId String? @map("tokenizer_id")
tokenizerConfig Json? @map("tokenizer_config")
+2 -1
View File
@@ -5,6 +5,7 @@ import {
} from "@/src/features/public-api/lib/apiKeys";
import { hash } from "bcryptjs";
import { parseArgs } from "node:util";
import { ModelUsageUnit } from "@/src/constants";
const options = {
environment: { type: "string" },
@@ -487,7 +488,7 @@ async function main() {
? { prompt: { connect: { id: prompt.id } } }
: {}),
},
unit: "TOKENS",
unit: ModelUsageUnit.Tokens,
},
});
if (Math.random() > 0.6)
+15 -14
View File
@@ -1,6 +1,7 @@
/** @jest-environment node */
import { pruneDatabase } from "@/src/__tests__/test-utils";
import { ModelUsageUnit } from "@/src/constants";
import { prisma } from "@/src/server/db";
describe("cost retrieval tests", () => {
@@ -111,7 +112,7 @@ describe("cost retrieval tests", () => {
projectId: null,
startDate: new Date("2023-12-01"),
tokenizerConfig: { tokensPerMessage: 3, tokensPerName: 1 },
unit: "TOKENS",
unit: ModelUsageUnit.Tokens,
},
});
@@ -130,7 +131,7 @@ describe("cost retrieval tests", () => {
model: "gpt-3.5-turbo",
internalModel: "gpt-3.5-turbo",
startTime: new Date("2024-01-01T00:00:00.000Z"),
unit: "TOKENS",
unit: ModelUsageUnit.Tokens,
promptTokens: input.promptTokens,
completionTokens: input.completionTokens,
totalTokens: input.totalTokens,
@@ -181,7 +182,7 @@ describe("cost retrieval tests", () => {
projectId: null,
startDate: new Date("2023-12-01"),
tokenizerConfig: { tokensPerMessage: 3, tokensPerName: 1 },
unit: "TOKENS",
unit: ModelUsageUnit.Tokens,
},
});
await prisma.model.create({
@@ -194,7 +195,7 @@ describe("cost retrieval tests", () => {
matchPattern: "(.*)(gpt-)(35|3.5)(-turbo)?(.*)",
startDate: new Date("2023-12-01"),
tokenizerConfig: { tokensPerMessage: 3, tokensPerName: 1 },
unit: "TOKENS",
unit: ModelUsageUnit.Tokens,
project: { connect: { id: "7a88fb47-b4e2-43b8-a06c-a5ce950dc53a" } },
},
});
@@ -214,7 +215,7 @@ describe("cost retrieval tests", () => {
model: "gpt-3.5-turbo",
internalModel: "gpt-3.5-turbo",
startTime: new Date("2024-01-01T00:00:00.000Z"),
unit: "TOKENS",
unit: ModelUsageUnit.Tokens,
promptTokens: 200,
completionTokens: 3000,
totalTokens: undefined,
@@ -252,7 +253,7 @@ describe("cost retrieval tests", () => {
projectId: null,
startDate: new Date("2023-12-01"),
tokenizerConfig: { tokensPerMessage: 3, tokensPerName: 1 },
unit: "TOKENS",
unit: ModelUsageUnit.Tokens,
},
});
await prisma.model.create({
@@ -265,7 +266,7 @@ describe("cost retrieval tests", () => {
matchPattern: "(.*)(gpt-)(35|3.5)(-turbo)?(.*)",
startDate: new Date("2023-12-02"),
tokenizerConfig: { tokensPerMessage: 3, tokensPerName: 1 },
unit: "TOKENS",
unit: ModelUsageUnit.Tokens,
},
});
@@ -284,7 +285,7 @@ describe("cost retrieval tests", () => {
model: "gpt-3.5-turbo",
internalModel: "gpt-3.5-turbo",
startTime: new Date("2024-01-01T00:00:00.000Z"),
unit: "TOKENS",
unit: ModelUsageUnit.Tokens,
promptTokens: 200,
completionTokens: 3000,
totalTokens: undefined,
@@ -317,7 +318,7 @@ describe("cost retrieval tests", () => {
matchPattern: "(.*)(gpt-)(35|3.5)(-turbo)?(.*)",
startDate: new Date("2023-12-02"),
tokenizerConfig: { tokensPerMessage: 3, tokensPerName: 1 },
unit: "TOKENS",
unit: ModelUsageUnit.Tokens,
},
});
await prisma.model.create({
@@ -331,7 +332,7 @@ describe("cost retrieval tests", () => {
startDate: new Date("2023-12-01"),
tokenizerConfig: { tokensPerMessage: 3, tokensPerName: 1 },
project: { connect: { id: "7a88fb47-b4e2-43b8-a06c-a5ce950dc53a" } },
unit: "TOKENS",
unit: ModelUsageUnit.Tokens,
},
});
@@ -350,7 +351,7 @@ describe("cost retrieval tests", () => {
model: "gpt-3.5-turbo",
internalModel: "gpt-3.5-turbo",
startTime: new Date("2024-01-01T00:00:00.000Z"),
unit: "TOKENS",
unit: ModelUsageUnit.Tokens,
promptTokens: 200,
completionTokens: 3000,
totalTokens: undefined,
@@ -383,7 +384,7 @@ describe("cost retrieval tests", () => {
matchPattern: "(.*)(gpt-)(35|3.5)(-turbo)?(.*)",
startDate: new Date("2023-12-02"),
tokenizerConfig: { tokensPerMessage: 3, tokensPerName: 1 },
unit: "TOKENS",
unit: ModelUsageUnit.Tokens,
},
});
await prisma.model.create({
@@ -397,7 +398,7 @@ describe("cost retrieval tests", () => {
startDate: new Date("2023-12-01"),
tokenizerConfig: { tokensPerMessage: 3, tokensPerName: 1 },
project: { connect: { id: "7a88fb47-b4e2-43b8-a06c-a5ce950dc53a" } },
unit: "TOKENS",
unit: ModelUsageUnit.Tokens,
},
});
@@ -416,7 +417,7 @@ describe("cost retrieval tests", () => {
model: "gpt-3.5-turbo",
internalModel: "gpt-3.5-turbo",
startTime: new Date("2024-01-01T00:00:00.000Z"),
unit: "TOKENS",
unit: ModelUsageUnit.Tokens,
promptTokens: 200,
completionTokens: 3000,
totalTokens: undefined,
@@ -1,27 +1,8 @@
import { orderByToPrismaSql } from "@/src/features/orderBy/server/orderByToPrisma";
import { tracesTableCols } from "@/src/server/api/definitions/tracesTable";
import { Prisma } from "@prisma/client";
// The test for the orderByToPrisma function
describe("orderByToPrisma (Convert orderBy to Prisma.sql)", () => {
test("orderByToPrisma returns default sql when orderBy=null", () => {
expect(orderByToPrismaSql(null, tracesTableCols)).toStrictEqual(
Prisma.sql`ORDER BY t.timestamp DESC`,
);
});
test("orderByToPrisma returns correct clause for orderBy column included in column defs", () => {
expect(
orderByToPrismaSql(
{
column: "latency",
order: "ASC",
},
tracesTableCols,
),
).toStrictEqual(Prisma.sql`ORDER BY tl.latency ASC`);
});
test("orderByToPrisma throws error for orderBy column not included in column defs", () => {
expect(() =>
orderByToPrismaSql(
@@ -33,4 +14,16 @@ describe("orderByToPrisma (Convert orderBy to Prisma.sql)", () => {
),
).toThrow(/Invalid filter column: InvalidCol/);
});
test("orderByToPrisma throws error for orderBy order that is not valid", () => {
expect(() =>
orderByToPrismaSql(
{
column: "latency",
order: "test" as "ASC" | "DESC",
},
tracesTableCols,
),
).toThrow(/Invalid order: test/);
});
});
+10 -8
View File
@@ -1,9 +1,11 @@
/** @jest-environment node */
import { prisma } from "@/src/server/db";
import { makeAPICall, pruneDatabase } from "@/src/__tests__/test-utils";
import { v4 as uuidv4 } from "uuid";
import { makeAPICall, pruneDatabase } from "@/src/__tests__/test-utils";
import { ModelUsageUnit } from "@/src/constants";
import { prisma } from "@/src/server/db";
describe("/api/public/generations API Endpoint", () => {
beforeEach(async () => await pruneDatabase());
@@ -13,9 +15,9 @@ describe("/api/public/generations API Endpoint", () => {
input: 100,
output: 200,
total: 100,
unit: "CHARACTERS",
unit: ModelUsageUnit.Characters,
},
expectedUnit: "CHARACTERS",
expectedUnit: ModelUsageUnit.Characters,
expectedPromptTokens: 100,
expectedCompletionTokens: 200,
expectedTotalTokens: 100,
@@ -23,9 +25,9 @@ describe("/api/public/generations API Endpoint", () => {
{
usage: {
total: 100,
unit: "CHARACTERS",
unit: ModelUsageUnit.Characters,
},
expectedUnit: "CHARACTERS",
expectedUnit: ModelUsageUnit.Characters,
expectedPromptTokens: 0,
expectedCompletionTokens: 0,
expectedTotalTokens: 100,
@@ -48,7 +50,7 @@ describe("/api/public/generations API Endpoint", () => {
expectedPromptTokens: 100,
expectedCompletionTokens: 200,
expectedTotalTokens: 100,
expectedUnit: "TOKENS",
expectedUnit: ModelUsageUnit.Tokens,
},
{
usage: {
@@ -57,7 +59,7 @@ describe("/api/public/generations API Endpoint", () => {
expectedPromptTokens: 0,
expectedCompletionTokens: 0,
expectedTotalTokens: 100,
expectedUnit: "TOKENS",
expectedUnit: ModelUsageUnit.Tokens,
},
{
usage: undefined,
+63 -29
View File
@@ -1,9 +1,11 @@
/** @jest-environment node */
import { v4 } from "uuid";
import { makeAPICall, pruneDatabase } from "@/src/__tests__/test-utils";
import { ModelUsageUnit } from "@/src/constants";
import { cleanEvent } from "@/src/pages/api/public/ingestion";
import { prisma } from "@/src/server/db";
import { v4 } from "uuid";
describe("/api/public/ingestion API Endpoint", () => {
beforeEach(async () => await pruneDatabase());
@@ -14,12 +16,12 @@ describe("/api/public/ingestion API Endpoint", () => {
input: 100,
output: 200,
total: 100,
unit: "CHARACTERS",
unit: ModelUsageUnit.Characters,
inputCost: 123,
outputCost: 456,
totalCost: 789,
},
expectedUnit: "CHARACTERS",
expectedUnit: ModelUsageUnit.Characters,
expectedPromptTokens: 100,
expectedCompletionTokens: 200,
expectedTotalTokens: 100,
@@ -27,13 +29,45 @@ describe("/api/public/ingestion API Endpoint", () => {
{
usage: {
total: 100,
unit: "CHARACTERS",
unit: ModelUsageUnit.Characters,
},
expectedUnit: "CHARACTERS",
expectedUnit: ModelUsageUnit.Characters,
expectedPromptTokens: 0,
expectedCompletionTokens: 0,
expectedTotalTokens: 100,
},
{
usage: {
total: 100,
unit: ModelUsageUnit.Milliseconds,
},
expectedUnit: ModelUsageUnit.Milliseconds,
expectedPromptTokens: 0,
expectedCompletionTokens: 0,
expectedTotalTokens: 100,
},
{
usage: {
input: 1,
output: 2,
unit: ModelUsageUnit.Images,
},
expectedUnit: ModelUsageUnit.Images,
expectedPromptTokens: 1,
expectedCompletionTokens: 2,
expectedTotalTokens: 3,
},
{
usage: {
input: 30,
output: 10,
unit: ModelUsageUnit.Seconds,
},
expectedUnit: ModelUsageUnit.Seconds,
expectedPromptTokens: 30,
expectedCompletionTokens: 10,
expectedTotalTokens: 40,
},
{
usage: {
total: 100,
@@ -52,7 +86,7 @@ describe("/api/public/ingestion API Endpoint", () => {
expectedPromptTokens: 100,
expectedCompletionTokens: 200,
expectedTotalTokens: 100,
expectedUnit: "TOKENS",
expectedUnit: ModelUsageUnit.Tokens,
},
{
usage: {
@@ -61,7 +95,7 @@ describe("/api/public/ingestion API Endpoint", () => {
expectedPromptTokens: 0,
expectedCompletionTokens: 0,
expectedTotalTokens: 100,
expectedUnit: "TOKENS",
expectedUnit: ModelUsageUnit.Tokens,
},
{
usage: undefined,
@@ -256,7 +290,7 @@ describe("/api/public/ingestion API Endpoint", () => {
{
observationExternalModel: "gpt-3.5",
observationStartTime: new Date("2021-01-01T00:00:00.000Z"),
modelUnit: "TOKENS",
modelUnit: ModelUsageUnit.Tokens,
expectedInternalModel: "gpt-3.5-turbo",
expectedPromptTokens: 5,
expectedCompletionTokens: 7,
@@ -265,7 +299,7 @@ describe("/api/public/ingestion API Endpoint", () => {
modelName: "gpt-3.5-turbo",
matchPattern: "(?i)^(gpt-)(35|3.5)(-turbo)?$",
startDate: new Date("2021-01-01T00:00:00.000Z"),
unit: "TOKENS",
unit: ModelUsageUnit.Tokens,
tokenizerId: "openai",
},
],
@@ -273,7 +307,7 @@ describe("/api/public/ingestion API Endpoint", () => {
{
observationExternalModel: "gpt-3.5",
observationStartTime: new Date("2021-01-01T00:00:00.000Z"),
modelUnit: "TOKENS",
modelUnit: ModelUsageUnit.Tokens,
expectedInternalModel: "gpt-3.5-turbo",
expectedPromptTokens: 5,
expectedCompletionTokens: 7,
@@ -282,7 +316,7 @@ describe("/api/public/ingestion API Endpoint", () => {
modelName: "gpt-3.5-turbo",
matchPattern: "(?i)^(gpt-)(35|3.5)(-turbo)?$",
startDate: null,
unit: "TOKENS",
unit: ModelUsageUnit.Tokens,
tokenizerId: "openai",
},
],
@@ -290,7 +324,7 @@ describe("/api/public/ingestion API Endpoint", () => {
{
observationExternalModel: "GPT-3.5",
observationStartTime: new Date("2021-01-01T00:00:00.000Z"),
modelUnit: "TOKENS",
modelUnit: ModelUsageUnit.Tokens,
expectedInternalModel: "gpt-3.5-turbo",
expectedPromptTokens: 5,
expectedCompletionTokens: 7,
@@ -299,7 +333,7 @@ describe("/api/public/ingestion API Endpoint", () => {
modelName: "gpt-3.5-turbo",
matchPattern: "(?i)^(gpt-)(35|3.5)(-turbo)?$",
startDate: new Date("2021-01-01T00:00:00.000Z"),
unit: "TOKENS",
unit: ModelUsageUnit.Tokens,
tokenizerId: "openai",
},
],
@@ -307,7 +341,7 @@ describe("/api/public/ingestion API Endpoint", () => {
{
observationExternalModel: "GPT-3.5",
observationStartTime: new Date("2021-01-01T00:00:00.000Z"),
modelUnit: "TOKENS",
modelUnit: ModelUsageUnit.Tokens,
expectedInternalModel: "gpt-3.5-turbo",
expectedPromptTokens: 5,
expectedCompletionTokens: 7,
@@ -316,14 +350,14 @@ describe("/api/public/ingestion API Endpoint", () => {
modelName: "gpt-3.5-turbo",
matchPattern: "(?i)^(gpt-)(35|3.5)(-turbo)?$",
startDate: new Date("2021-01-01T00:00:00.000Z"),
unit: "TOKENS",
unit: ModelUsageUnit.Tokens,
tokenizerId: "openai",
},
{
modelName: "gpt-3.5-turbo-new",
matchPattern: "(?i)^(gpt-)(35|3.5)(-turbo)?$",
startDate: new Date("2021-01-01T10:00:00.000Z"),
unit: "TOKENS",
unit: ModelUsageUnit.Tokens,
tokenizerId: "openai",
},
],
@@ -331,7 +365,7 @@ describe("/api/public/ingestion API Endpoint", () => {
{
observationExternalModel: "GPT-3.5",
observationStartTime: new Date("2021-01-02T00:00:00.000Z"),
modelUnit: "TOKENS",
modelUnit: ModelUsageUnit.Tokens,
expectedInternalModel: "gpt-3.5-turbo",
expectedPromptTokens: 5,
expectedCompletionTokens: 7,
@@ -340,14 +374,14 @@ describe("/api/public/ingestion API Endpoint", () => {
modelName: "gpt-3.5-turbo-new",
matchPattern: "(?i)^(gpt-)(35|3.5)(-turbo)?$",
startDate: new Date("2021-01-01T00:00:00.000Z"),
unit: "TOKENS",
unit: ModelUsageUnit.Tokens,
tokenizerId: "openai",
},
{
modelName: "gpt-3.5-turbo",
matchPattern: "(?i)^(gpt-)(35|3.5)(-turbo)?$",
startDate: new Date("2021-01-01T10:00:00.000Z"),
unit: "TOKENS",
unit: ModelUsageUnit.Tokens,
tokenizerId: "openai",
tokenizerModel: "gpt-3.5-turbo",
},
@@ -356,7 +390,7 @@ describe("/api/public/ingestion API Endpoint", () => {
{
observationExternalModel: "ft:gpt-3.5-turbo-1106:my-org:custom_suffix:id",
observationStartTime: new Date("2022-01-01T10:00:00.000Z"),
modelUnit: "TOKENS",
modelUnit: ModelUsageUnit.Tokens,
expectedInternalModel: "ft:gpt-3.5-turbo-1106",
expectedPromptTokens: 0,
expectedCompletionTokens: 0,
@@ -365,7 +399,7 @@ describe("/api/public/ingestion API Endpoint", () => {
modelName: "ft:gpt-3.5-turbo-1106",
matchPattern: "(?i)^(ft:)(gpt-3.5-turbo-1106:)(.+)(:)(.*)(:)(.+)$",
startDate: new Date("2022-01-01T00:00:00.000Z"),
unit: "TOKENS",
unit: ModelUsageUnit.Tokens,
tokenizerId: "openai",
},
],
@@ -373,7 +407,7 @@ describe("/api/public/ingestion API Endpoint", () => {
{
observationExternalModel: "ft:babbage-002:my-org#2:custom_suffix-2:id",
observationStartTime: new Date("2022-01-01T10:00:00.000Z"),
modelUnit: "TOKENS",
modelUnit: ModelUsageUnit.Tokens,
expectedInternalModel: "ft:babbage-002",
expectedPromptTokens: 0,
expectedCompletionTokens: 0,
@@ -382,7 +416,7 @@ describe("/api/public/ingestion API Endpoint", () => {
modelName: "ft:babbage-002",
matchPattern: "(?i)^(ft:)(babbage-002:)(.+)(:)(.*)(:)(.+)$",
startDate: new Date("2022-01-01T00:00:00.000Z"),
unit: "TOKENS",
unit: ModelUsageUnit.Tokens,
tokenizerId: "openai",
},
],
@@ -390,7 +424,7 @@ describe("/api/public/ingestion API Endpoint", () => {
{
observationExternalModel: "GPT-4",
observationStartTime: new Date("2021-01-01T00:00:00.000Z"),
modelUnit: "TOKENS",
modelUnit: ModelUsageUnit.Tokens,
expectedInternalModel: null,
expectedPromptTokens: 0,
expectedCompletionTokens: 0,
@@ -399,7 +433,7 @@ describe("/api/public/ingestion API Endpoint", () => {
modelName: "gpt-3.5-turbo",
matchPattern: "(?i)^(gpt-)(35|3.5)(-turbo)?$",
startDate: new Date("2021-01-01T00:00:00.000Z"),
unit: "TOKENS",
unit: ModelUsageUnit.Tokens,
tokenizerId: "openai",
},
],
@@ -407,7 +441,7 @@ describe("/api/public/ingestion API Endpoint", () => {
{
observationExternalModel: "GPT-3",
observationStartTime: new Date("2021-01-01T00:00:00.000Z"),
modelUnit: "CHARACTERS",
modelUnit: ModelUsageUnit.Characters,
expectedInternalModel: null,
expectedPromptTokens: 0,
expectedCompletionTokens: 0,
@@ -416,7 +450,7 @@ describe("/api/public/ingestion API Endpoint", () => {
modelName: "gpt-3.5-turbo",
matchPattern: "(?i)^(gpt-)(35|3.5)(-turbo)?$",
startDate: new Date("2021-01-01T00:00:00.000Z"),
unit: "TOKENS",
unit: ModelUsageUnit.Tokens,
tokenizerId: "openai",
},
],
@@ -886,7 +920,7 @@ describe("/api/public/ingestion API Endpoint", () => {
modelName: "gpt-3.5",
matchPattern: "(?i)^(gpt-)(35|3.5)(-turbo)?$",
startDate: new Date("2021-01-01T00:00:00.000Z"),
unit: "TOKENS",
unit: ModelUsageUnit.Tokens,
tokenizerId: "openai",
tokenizerConfig: {
tokensPerMessage: 3,
@@ -968,7 +1002,7 @@ describe("/api/public/ingestion API Endpoint", () => {
modelName: "gpt-3.5",
matchPattern: "(?i)^(gpt-)(35|3.5)(-turbo)?$",
startDate: new Date("2021-01-01T00:00:00.000Z"),
unit: "TOKENS",
unit: ModelUsageUnit.Tokens,
tokenizerId: "openai",
tokenizerConfig: {
tokensPerMessage: 3,
+6 -5
View File
@@ -2,6 +2,7 @@
import { modelMatch } from "@/scripts/model-match";
import { pruneDatabase } from "@/src/__tests__/test-utils";
import { ModelUsageUnit } from "@/src/constants";
import { prisma } from "@/src/server/db";
describe("model match", () => {
@@ -17,7 +18,7 @@ describe("model match", () => {
totalPrice: "0.1",
matchPattern: "(.*)(gpt-3.5-turbo)?(.*)",
projectId: null,
unit: "TOKENS",
unit: ModelUsageUnit.Tokens,
tokenizerConfig: {
tokensPerMessage: 3,
tokensPerName: 1,
@@ -35,7 +36,7 @@ describe("model match", () => {
totalPrice: "0.1",
matchPattern: "(.*)(claude-1.3)?(.*)",
projectId: null,
unit: "TOKENS",
unit: ModelUsageUnit.Tokens,
tokenizerId: "claude",
},
});
@@ -48,7 +49,7 @@ describe("model match", () => {
projectId: "7a88fb47-b4e2-43b8-a06c-a5ce950dc53a",
model: "gpt-3.5-turbo",
startTime: new Date("2024-01-01T00:00:00.000Z"),
unit: "TOKENS",
unit: ModelUsageUnit.Tokens,
promptTokens: 200,
completionTokens: 3000,
input: "I am a prompt",
@@ -59,7 +60,7 @@ describe("model match", () => {
projectId: "7a88fb47-b4e2-43b8-a06c-a5ce950dc53a",
model: "claude-1.3",
startTime: new Date("2024-01-01T00:00:00.000Z"),
unit: "TOKENS",
unit: ModelUsageUnit.Tokens,
input: "I am a prompt",
output: "I am a completion",
},
@@ -68,7 +69,7 @@ describe("model match", () => {
projectId: "7a88fb47-b4e2-43b8-a06c-a5ce950dc53a",
model: "claude-1.3",
startTime: new Date("2024-01-01T00:00:00.000Z"),
unit: "TOKENS",
unit: ModelUsageUnit.Tokens,
input: "I am a prompt",
output: "I am a completion",
},
+8 -6
View File
@@ -1,8 +1,10 @@
/** @jest-environment node */
import { prisma } from "@/src/server/db";
import { makeAPICall, pruneDatabase } from "@/src/__tests__/test-utils";
import { v4 as uuidv4 } from "uuid";
import { makeAPICall, pruneDatabase } from "@/src/__tests__/test-utils";
import { ModelUsageUnit } from "@/src/constants";
import { prisma } from "@/src/server/db";
import { type ObservationView } from "@prisma/client";
describe("/api/public/observations API Endpoint", () => {
@@ -35,7 +37,7 @@ describe("/api/public/observations API Endpoint", () => {
totalPrice: "0.1",
matchPattern: "(.*)(gpt-)(35|3.5)(-turbo)?(.*)",
projectId: null,
unit: "TOKENS",
unit: ModelUsageUnit.Tokens,
},
});
@@ -59,7 +61,7 @@ describe("/api/public/observations API Endpoint", () => {
connect: { id: "7a88fb47-b4e2-43b8-a06c-a5ce950dc53a" },
},
internalModel: "gpt-3.5-turbo",
unit: "TOKENS",
unit: ModelUsageUnit.Tokens,
},
});
@@ -120,7 +122,7 @@ describe("/api/public/observations API Endpoint", () => {
totalPrice: "0.1",
matchPattern: "(.*)(gpt-)(35|3.5)(-turbo)?(.*)",
projectId: null,
unit: "TOKENS",
unit: ModelUsageUnit.Tokens,
},
});
@@ -140,7 +142,7 @@ describe("/api/public/observations API Endpoint", () => {
completionTokens: 20,
totalTokens: 30,
version: "2.0.0",
unit: "TOKENS",
unit: ModelUsageUnit.Tokens,
type: "GENERATION",
project: {
connect: { id: "7a88fb47-b4e2-43b8-a06c-a5ce950dc53a" },
+2 -1
View File
@@ -1,3 +1,4 @@
import { ModelUsageUnit } from "@/src/constants";
import { tokenCount } from "@/src/features/ingest/lib/usage";
describe("Token Count Functions", () => {
@@ -19,7 +20,7 @@ describe("Token Count Functions", () => {
inputPrice: null,
outputPrice: null,
totalPrice: null,
unit: "TOKENS",
unit: ModelUsageUnit.Tokens,
};
};
+3 -2
View File
@@ -1,7 +1,8 @@
import { VERSION } from "@/src/constants/VERSION";
import { AlertTriangle } from "lucide-react";
import { VERSION } from "@/src/constants";
import { env } from "@/src/env.mjs";
import { cn } from "@/src/utils/tailwind";
import { AlertTriangle } from "lucide-react";
export const LangfuseIcon = ({
size = 32,
+1 -1
View File
@@ -35,7 +35,7 @@ const modelConfigDescriptions = {
outputPrice: "Price per unit of output",
totalPrice:
"Price per unit, for models that don't have input/output specific prices",
unit: "Unit of measurement for model, can be TOKENS or CHARACTERS.",
unit: "Unit of measurement for generative model, can be TOKENS, CHARACTERS, SECONDS, MILLISECONDS, or IMAGES.",
tokenizerId:
"Tokenizer used for this model to calculate token counts if none are ingested. Pick from list of supported tokenizers.",
config:
+1 -1
View File
@@ -1 +1 @@
export const VERSION = "v2.1.2";
export const VERSION = "v2.2.0";
+9
View File
@@ -0,0 +1,9 @@
export { VERSION } from "./VERSION";
export enum ModelUsageUnit {
Characters = "CHARACTERS",
Tokens = "TOKENS",
Seconds = "SECONDS",
Milliseconds = "MILLISECONDS",
Images = "IMAGES",
}
@@ -68,6 +68,8 @@ export function BaseTimeSeriesChart(props: {
noDataText="No data"
showLegend={props.showLegend}
showAnimation={true}
onValueChange={() => {}}
enableLegendSlider={true}
/>
);
}
+15 -13
View File
@@ -1,7 +1,12 @@
import { Button } from "@/src/components/ui/button";
import * as z from "zod";
import { zodResolver } from "@hookform/resolvers/zod";
import { usePostHog } from "posthog-js/react";
import { useState } from "react";
import { useForm } from "react-hook-form";
import JsonView from "react18-json-view";
import * as z from "zod";
import { DatePicker } from "@/src/components/date-picker";
import Header from "@/src/components/layouts/header";
import { Button } from "@/src/components/ui/button";
import {
Form,
FormControl,
@@ -11,6 +16,7 @@ import {
FormLabel,
FormMessage,
} from "@/src/components/ui/form";
import { Input } from "@/src/components/ui/input";
import {
Select,
SelectContent,
@@ -18,14 +24,10 @@ import {
SelectTrigger,
SelectValue,
} from "@/src/components/ui/select";
import { api } from "@/src/utils/api";
import { useState } from "react";
import { usePostHog } from "posthog-js/react";
import { Input } from "@/src/components/ui/input";
import { DatePicker } from "@/src/components/date-picker";
import Header from "@/src/components/layouts/header";
import { ModelUsageUnit } from "@/src/constants";
import { AutoComplete } from "@/src/features/prompts/components/auto-complete";
import JsonView from "react18-json-view";
import { api } from "@/src/utils/api";
import { zodResolver } from "@hookform/resolvers/zod";
const formSchema = z.object({
modelName: z.string().min(1),
@@ -49,7 +51,7 @@ const formSchema = z.object({
message: "Price needs to be numeric",
})
.optional(),
unit: z.enum(["TOKENS", "CHARACTERS"]),
unit: z.nativeEnum(ModelUsageUnit),
tokenizerId: z.enum(["openai", "claude", "None"]),
tokenizerConfig: z.string().refine(
(value) => {
@@ -81,7 +83,7 @@ export const NewModelForm = (props: {
inputPrice: "",
outputPrice: "",
totalPrice: "",
unit: "TOKENS",
unit: ModelUsageUnit.Tokens,
tokenizerId: "None",
tokenizerConfig: "{}",
},
@@ -233,7 +235,7 @@ export const NewModelForm = (props: {
</SelectTrigger>
</FormControl>
<SelectContent>
{["TOKENS", "CHARACTERS"].map((unit) => (
{Object.values(ModelUsageUnit).map((unit) => (
<SelectItem value={unit} key={unit}>
{unit}
</SelectItem>
+13 -2
View File
@@ -1,6 +1,7 @@
import { type OrderByState } from "@/src/features/orderBy/types";
import { type ColumnDefinition } from "@/src/server/api/interfaces/tableDefinition";
import { Prisma } from "@prisma/client";
import { z } from "zod";
/**
* Convert orderBy to SQL ORDER BY clause
@@ -13,7 +14,7 @@ export function orderByToPrismaSql(
tableColumns: ColumnDefinition[],
): Prisma.Sql {
if (!orderBy) {
return Prisma.sql([`ORDER BY t.timestamp DESC`]);
return Prisma.sql`ORDER BY t.timestamp DESC`;
}
// Get column definition to map column to internal name, e.g. "t.id"
const col = tableColumns.find(
@@ -21,10 +22,20 @@ export function orderByToPrismaSql(
// It's less error-prone & decouples data fetching from the human-readable UI labels
(c) => c.name === orderBy.column || c.id === orderBy.column,
);
if (!col) {
console.log("Invalid filter column", orderBy.column);
throw new Error("Invalid filter column: " + orderBy.column);
}
return Prisma.sql([`ORDER BY ${col.internal} ${orderBy.order}`]);
// Assert that orderBy.order is either "asc" or "desc"
const orderByOrder = z.enum(["ASC", "DESC"]);
const order = orderByOrder.safeParse(orderBy.order);
if (!order.success) {
console.log("Invalid order", orderBy.order);
throw new Error("Invalid order: " + orderBy.order);
}
// Both column and order are safe, can use raw SQL
return Prisma.raw(`ORDER BY ${col.internal} ${order.data}`);
}
+3 -1
View File
@@ -91,7 +91,9 @@ export async function verifyAuthHeaderAndReturnScope(
console.error("Error verifying auth header: ", error);
return {
validKey: false,
error: error instanceof Error ? error.message : "Authorization error",
error:
(error instanceof Error ? error.message : "Authorization error") +
". Confirm that you've configured the correct host.",
};
}
return {
@@ -1,13 +1,15 @@
import { ObservationLevel } from "@prisma/client";
import { jsonSchema } from "@/src/utils/zod";
import { z } from "zod";
import lodash from "lodash";
import { z } from "zod";
import { ModelUsageUnit } from "@/src/constants";
import { jsonSchema } from "@/src/utils/zod";
import { ObservationLevel } from "@prisma/client";
export const Usage = z.object({
input: z.number().int().nullish(),
output: z.number().int().nullish(),
total: z.number().int().nullish(),
unit: z.enum(["TOKENS", "CHARACTERS"]).nullish(),
unit: z.nativeEnum(ModelUsageUnit).nullish(),
inputCost: z.number().nullish(),
outputCost: z.number().nullish(),
totalCost: z.number().nullish(),
@@ -17,7 +19,7 @@ const MixedUsage = z.object({
input: z.number().int().nullish(),
output: z.number().int().nullish(),
total: z.number().int().nullish(),
unit: z.enum(["TOKENS", "CHARACTERS"]).nullish(),
unit: z.nativeEnum(ModelUsageUnit).nullish(),
promptTokens: z.number().int().nullish(),
completionTokens: z.number().int().nullish(),
totalTokens: z.number().int().nullish(),
@@ -40,7 +42,7 @@ export const usage = MixedUsage.nullish()
input: v.promptTokens,
output: v.completionTokens,
total: v.totalTokens,
unit: "TOKENS",
unit: ModelUsageUnit.Tokens,
};
}
// if we get the new generic format, we do not set a default
+1 -1
View File
@@ -1,4 +1,4 @@
import { VERSION } from "@/src/constants/VERSION";
import { VERSION } from "@/src/constants";
import { prisma } from "@/src/server/db";
import { Prisma } from "@prisma/client";
import { PostHog } from "posthog-node";
+1 -1
View File
@@ -1,4 +1,4 @@
import { VERSION } from "@/src/constants/VERSION";
import { VERSION } from "@/src/constants";
import { cors, runMiddleware } from "@/src/features/public-api/server/cors";
import { telemetry } from "@/src/features/telemetry";
import { prisma } from "@/src/server/db";
+3 -2
View File
@@ -1,11 +1,12 @@
import { z } from "zod";
import { ModelUsageUnit } from "@/src/constants";
import { throwIfNoAccess } from "@/src/features/rbac/utils/checkAccess";
import {
createTRPCRouter,
protectedProjectProcedure,
} from "@/src/server/api/trpc";
import { paginationZod } from "@/src/utils/zod";
import { throwIfNoAccess } from "@/src/features/rbac/utils/checkAccess";
import { Prisma } from "@prisma/client";
import { TRPCError } from "@trpc/server";
@@ -93,7 +94,7 @@ export const modelRouter = createTRPCRouter({
inputPrice: z.number().nonnegative().optional(),
outputPrice: z.number().nonnegative().optional(),
totalPrice: z.number().nonnegative().optional(),
unit: z.enum(["TOKENS", "CHARACTERS"]),
unit: z.nativeEnum(ModelUsageUnit),
tokenizerId: z.enum(["openai", "claude"]).optional(),
tokenizerConfig: z.record(z.union([z.string(), z.number()])).optional(),
}),