Compare commits

...
84 Commits
Author SHA1 Message Date
Marc Klingen 89d38ff6ad chore: release v2.10.3
CI/CD / push-docker-image (push) Blocked by required conditions
CI/CD / tests (18) (push) Failing after 58s
CI/CD / tests (20) (push) Failing after 49s
CI/CD / e2e-tests (push) Failing after 48s
CI/CD / test-docker-build (push) Successful in 2m53s
release.yml / release (push) Failing after 3s
CI/CD / lint (push) Successful in 4m51s
CI/CD / all-ci-passed (push) Waiting to run
2024-03-07 00:52:54 +01:00
Marc KlingenandGitHub 8d7b334521 refactor: remove separate identify() to reduce number of posthog events (#1263) 2024-03-06 23:27:21 +00:00
Marc KlingenandGitHub a374a378a0 fix: dashboard state management (#1349) 2024-03-06 23:23:11 +00:00
Max Deichmann f95a6943a6 chore: release v2.10.2
CI/CD / push-docker-image (push) Blocked by required conditions
CI/CD / test-docker-build (push) Failing after 2m15s
CI/CD / lint (push) Successful in 4m41s
CI/CD / tests (18) (push) Failing after 54s
CI/CD / tests (20) (push) Failing after 1m49s
release.yml / release (push) Failing after 4s
CI/CD / e2e-tests (push) Failing after 1m39s
CI/CD / all-ci-passed (push) Waiting to run
2024-03-06 22:11:10 +01:00
Max DeichmannandGitHub fec89b8c62 perf: remove sessions total latency (#1347) 2024-03-06 20:46:06 +01:00
Max Deichmann a10a6a7ca5 chore: release v2.10.1
CI/CD / push-docker-image (push) Blocked by required conditions
CI/CD / tests (18) (push) Failing after 53s
CI/CD / tests (20) (push) Failing after 48s
CI/CD / e2e-tests (push) Failing after 1m13s
release.yml / release (push) Failing after 13s
CI/CD / test-docker-build (push) Successful in 4m3s
CI/CD / lint (push) Successful in 4m14s
CI/CD / all-ci-passed (push) Waiting to run
2024-03-06 17:12:20 +01:00
Max DeichmannandGitHub 8f32ef935b fix: generations pagination (#1345) 2024-03-06 15:49:21 +00:00
Max DeichmannandGitHub 4f0b309e0d fix: filter users table for null users (#1342) 2024-03-06 15:24:07 +00:00
Max DeichmannandGitHub c424a5578e perf: generations table performance (#1341) 2024-03-06 15:13:02 +00:00
Marc Klingen 2113c684a4 chore: release v2.10.0
CI/CD / push-docker-image (push) Blocked by required conditions
CI/CD / tests (18) (push) Failing after 57s
CI/CD / tests (20) (push) Failing after 49s
CI/CD / e2e-tests (push) Failing after 47s
release.yml / release (push) Failing after 3s
CI/CD / test-docker-build (push) Successful in 3m27s
CI/CD / lint (push) Successful in 6m1s
CI/CD / all-ci-passed (push) Waiting to run
2024-03-06 14:38:25 +01:00
Marc KlingenandGitHub d900056f69 ci: tag docker containers with major version (#1340) 2024-03-06 14:33:49 +01:00
a2930f3f2a feat(generations): extend CSV and JSON export (#1265)
Co-authored-by: Max Deichmann <m.deichmann@tum.de>
2024-03-06 13:24:35 +00:00
Max DeichmannandGitHub 9a3fa2b461 fix: correctly calculate total events (#1339) 2024-03-06 13:10:06 +00:00
Max DeichmannandGitHub 4ac3b13ca6 perf: delayed loading for user metrics (#1338) 2024-03-06 13:00:37 +00:00
Max DeichmannandGitHub 4c32113ec3 perf: user tables (#1329) 2024-03-05 17:23:51 +00:00
Richard KrümmelandGitHub 7f81135e6b feat(traces): extend table (#1278) 2024-03-05 17:11:26 +01:00
Marc KlingenandGitHub 4a362ee10f fix: GET /traces endpoint, typing of params, return empty [] instead of null (#1324) 2024-03-05 15:42:43 +01:00
Richard KrümmelandGitHub 04374dd0b3 feat(sessions): extend table (#1271) 2024-03-05 13:43:52 +00:00
Richard KrümmelandGitHub a69571cedc feat(datasets): rename datasets (#1203) 2024-03-05 14:10:32 +01:00
Max DeichmannandGitHub 53e78ee249 fix: fix indices (#1322) 2024-03-05 13:36:31 +01:00
Max DeichmannandGitHub 64c0e26da6 perf: users table (#1320) 2024-03-05 12:27:18 +01:00
Max DeichmannandGitHub fa52811224 fix: scores table filtering (#1319) 2024-03-05 08:32:08 +00:00
Max DeichmannandGitHub 213d9da88a perf: improve scores table latency (#1315) 2024-03-05 09:25:18 +01:00
Max DeichmannandGitHub 8611afd533 perf: latency chart performance (#1314) 2024-03-04 20:38:29 +00:00
Max DeichmannandGitHub e96a3bbf6e feat: add tooltip to latency tables (#1313) 2024-03-04 19:40:19 +00:00
Max DeichmannandGitHub 60e636e37d feat: add traces, spans, generations latency tables (#1312) 2024-03-04 16:37:57 +00:00
Max DeichmannandGitHub e9e8319099 fix: adjust sentry sampling rate (#1311) 2024-03-04 11:11:12 +00:00
Marc Klingen 8ee0e611d9 chore: release v2.9.1
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-03-02 04:15:40 +01:00
Marc Klingen b7b9cc8dd1 fix(ui): use Textarea for dataset item edits instead of json editor
Reverts #1171
2024-03-02 04:10:21 +01:00
Marc KlingenandGitHub 21240cb594 chore(prompts): remove beta flag (#1304) 2024-03-01 23:22:07 +00:00
Max DeichmannandGitHub fdda5db1a3 feat: increase scale of dashboard USD numbers (#1301) 2024-03-01 18:42:52 +01:00
Max DeichmannandGitHub 0538f27caf fix: fix empty score names (#1299) 2024-03-01 15:10:30 +01:00
Marc KlingenandGitHub c73bc5a77f fix(ui): AreaChart only for total traces, all others use LineChart (#1297) 2024-03-01 13:22:57 +00:00
Max DeichmannandGitHub 9204c9dc69 perf: show 10 generations in table when i/o is selected (#1294) 2024-03-01 09:53:40 +01:00
Marc Klingen feb935e737 chore: switch to svg icon 2024-03-01 02:00:34 +01:00
Max Deichmann e4a029988f chore: release v2.9.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-29 14:50:13 +01:00
Marc Klingen d8bb7703ae fix(ui): second level headings should be h3 2024-02-29 12:24:55 +01:00
Marc Klingen bd7574411e chore: add npm run dx to root 2024-02-29 12:02:24 +01:00
Marc Klingen 2f55acec7c docs: update readme 2024-02-28 23:15:42 +01:00
SebandGitHub 78207ba274 chore: improve date picker formatting (#1283) 2024-02-28 20:14:16 +01:00
SebandGitHub 2250be58a5 docs: fix link to db schema (#1282) 2024-02-28 20:12:49 +01:00
Max DeichmannandGitHub 338517828c perf: increase sample rate for POST and trpc (#1284) 2024-02-28 19:06:10 +00:00
Max DeichmannandGitHub 2e80d4b475 perf: improve dashboard performance (#1281) 2024-02-28 16:51:38 +01:00
Marc KlingenandGitHub 45c9af76d8 fix(api): add input, output, sessionId, public to GET /traces (#1280) 2024-02-28 13:47:40 +00:00
Max DeichmannandGitHub bc27618c0e perf: improve generations table performance (#1279) 2024-02-28 13:41:33 +00:00
Max DeichmannandGitHub a4c8f0b702 perf: improve traces table performance (#1276) 2024-02-28 13:04:11 +00:00
Max DeichmannandGitHub 787eb90c54 perf: improve observations view and all traces (#1275) 2024-02-28 09:48:20 +00:00
Max DeichmannandGitHub 9b4601debf refactor: add load database setup script (#1273) 2024-02-27 23:43:30 +00:00
Max DeichmannandGitHub fcc0ee922f refactor: add sentry users to API (#1269) 2024-02-27 16:17:37 +01:00
Max DeichmannandGitHub 3271c4abd0 fix: observations index (#1267) 2024-02-27 14:33:56 +01:00
Max DeichmannandGitHub 2dbb9fec87 fix: fix observations index (#1266) 2024-02-27 12:42:32 +01:00
e7438c05b8 feat(generation): extend generations table (#1216)
Co-authored-by: Max Deichmann <m.deichmann@tum.de>
2024-02-27 11:20:27 +00:00
Marc Klingen 45fcf8902b fix(self-host): event mapping 2024-02-27 02:40:54 +01:00
Max DeichmannandGitHub a4bfdb25a5 perf: revert traces router query (#1261)
revert
2024-02-26 22:37:35 +00:00
Max DeichmannandGitHub 462e8a7b8c perf: traces table performance improvements (#1256) 2024-02-26 22:57:53 +01:00
Marc KlingenandGitHub 86edd502b3 feat(ui): add alert that only ChatML generations is exported as JSONL (#1257) 2024-02-26 19:56:41 +00:00
Max DeichmannandGitHub 01a7e679fa fix: correctly return 500 and 400 API errors (#1253) 2024-02-26 12:44:03 +00:00
Marc KlingenandGitHub c6406e1ddb fix(ui): sort/filter sessions by total cost (#1254) 2024-02-26 11:35:20 +00:00
Max DeichmannandGitHub 82d4881dcf fix: improve contributing.md (#1252) 2024-02-26 09:23:51 +00:00
Max DeichmannandGitHub 42d3167591 fix: docs and root level commands (#1251) 2024-02-26 08:52:09 +00:00
Marc KlingenandGitHub 977ac39ec5 docs(api): improve api reference descriptions (#1244) 2024-02-23 19:44:11 +00:00
Marc Klingen e4d8db6a34 chore: release v2.8.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-23 20:23:00 +01:00
Marc KlingenandGitHub a39bbf541d feat(api): add GET /score/[scoreId] (#1242) 2024-02-23 19:20:27 +00:00
Max DeichmannandGitHub eef5218dbd refactor: add worker tests (#1241) 2024-02-23 17:44:54 +00:00
Marc KlingenandGitHub b5e802171b fix(api): deduplicate score and observation ids in GET /traces (#1240) 2024-02-23 17:38:55 +00:00
Max DeichmannandGitHub 96c4f28b5b refactor: linting worker (#1239) 2024-02-23 17:34:16 +00:00
Max DeichmannandGitHub 8ad4a46850 feat: add database connection to worker (#1238) 2024-02-23 16:55:16 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>Max Deichmann
d8f2d6cf4e chore(deps): bump the prisma group in /web with 2 updates (#1231)
Bumps the prisma group in /web with 2 updates: [@prisma/client](https://github.com/prisma/prisma/tree/HEAD/packages/client) and [prisma](https://github.com/prisma/prisma/tree/HEAD/packages/cli).


Updates `@prisma/client` from 5.9.1 to 5.10.2
- [Release notes](https://github.com/prisma/prisma/releases)
- [Commits](https://github.com/prisma/prisma/commits/5.10.2/packages/client)

Updates `prisma` from 5.9.1 to 5.10.2
- [Release notes](https://github.com/prisma/prisma/releases)
- [Commits](https://github.com/prisma/prisma/commits/5.10.2/packages/cli)

---
updated-dependencies:
- dependency-name: "@prisma/client"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: prisma
- dependency-name: prisma
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: prisma
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Max Deichmann <m.deichmann@tum.de>
2024-02-23 16:50:10 +00:00
b8639ebb3b feat: use Json editor for dataset item editor (#1171)
Co-authored-by: gitstart-langfuse <gitstart-langfuse@users.noreply.github.com>
Co-authored-by: Max Deichmann <m.deichmann@tum.de>
2024-02-23 14:46:27 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
8be73970c2 chore(deps): bump the sentry group in /web with 3 updates (#1230)
Bumps the sentry group in /web with 3 updates: [@sentry/nextjs](https://github.com/getsentry/sentry-javascript), [@sentry/profiling-node](https://github.com/getsentry/sentry-javascript) and [@sentry/types](https://github.com/getsentry/sentry-javascript).


Updates `@sentry/nextjs` from 7.101.1 to 7.102.1
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/7.102.1/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/7.101.1...7.102.1)

Updates `@sentry/profiling-node` from 7.101.1 to 7.102.1
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/7.102.1/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/7.101.1...7.102.1)

Updates `@sentry/types` from 7.101.1 to 7.102.1
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/7.102.1/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/7.101.1...7.102.1)

---
updated-dependencies:
- dependency-name: "@sentry/nextjs"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: sentry
- dependency-name: "@sentry/profiling-node"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: sentry
- dependency-name: "@sentry/types"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: sentry
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-23 14:34:10 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>Max Deichmann
e18ab26bb5 chore(deps): bump @aws-sdk/lib-storage from 3.511.0 to 3.515.0 in /web (#1233)
Bumps [@aws-sdk/lib-storage](https://github.com/aws/aws-sdk-js-v3/tree/HEAD/lib/lib-storage) from 3.511.0 to 3.515.0.
- [Release notes](https://github.com/aws/aws-sdk-js-v3/releases)
- [Changelog](https://github.com/aws/aws-sdk-js-v3/blob/main/lib/lib-storage/CHANGELOG.md)
- [Commits](https://github.com/aws/aws-sdk-js-v3/commits/v3.515.0/lib/lib-storage)

---
updated-dependencies:
- dependency-name: "@aws-sdk/lib-storage"
  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>
Co-authored-by: Max Deichmann <m.deichmann@tum.de>
2024-02-23 14:28:52 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>Max Deichmann
095478869d chore(deps-dev): bump release-it from 17.0.5 to 17.1.1 in /web (#1234)
Bumps [release-it](https://github.com/release-it/release-it) from 17.0.5 to 17.1.1.
- [Release notes](https://github.com/release-it/release-it/releases)
- [Changelog](https://github.com/release-it/release-it/blob/main/CHANGELOG.md)
- [Commits](https://github.com/release-it/release-it/compare/17.0.5...17.1.1)

---
updated-dependencies:
- dependency-name: release-it
  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>
Co-authored-by: Max Deichmann <m.deichmann@tum.de>
2024-02-23 14:23:04 +00:00
Marc KlingenandGitHub 4db7dab8ae fix(export): messages key in jsonl output format (#1236) 2024-02-23 13:54:31 +00:00
Max DeichmannandGitHub 086d26b041 fix: fix dependabot in new repo structure (#1228) 2024-02-23 09:35:32 +00:00
Max Deichmann 5fd042c7b1 chore: release v2.7.2
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-23 10:24:30 +01:00
Max DeichmannandGitHub dc37f1a58a feat: add worker container and redis (#1224) 2024-02-23 09:13:28 +00:00
Marc KlingenandGitHub bc4597e183 fix(ui): enable selection of text in trace inputs/outputs (#1227) 2024-02-23 02:37:45 +00:00
Marc Klingen 9bb1caf738 chore: fix paths in docs after migration to /web 2024-02-23 03:30:24 +01:00
Marc KlingenandGitHub 3ab4eb6341 docs: fix db schema in contributing.md 2024-02-23 01:14:58 +01:00
Max DeichmannandGitHub 5944611b51 fix: setup prettier (#1226) 2024-02-22 13:51:11 +00:00
Max Deichmann e439c81512 chore: release v2.7.1
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-22 14:08:26 +01:00
Max DeichmannandGitHub 799d32fa21 move nextjs into web directory (#1223) 2024-02-22 14:02:28 +01:00
Max DeichmannandGitHub 7927d0013f feat(API): catch prisma errors individually for public apis (#1215) 2024-02-21 21:05:19 +00:00
Marc KlingenandGitHub 147262a437 fix(ui): long observation/trace names should break instead of overflow (#1218) 2024-02-21 00:07:11 +00:00
517 changed files with 34044 additions and 19821 deletions
+3
View File
@@ -0,0 +1,3 @@
node_modules
build
coverage
+28 -1
View File
@@ -6,7 +6,34 @@
version: 2
updates:
- package-ecosystem: npm
directory: "/" # Location of package manifests
directory: "/worker" # Location of package manifests
schedule:
interval: "daily"
rebase-strategy: "disabled" # use dependabot-rebase-stale
commit-message:
prefix: chore
prefix-development: chore
include: scope
ignore:
- dependency-name: "@types/node"
- dependency-name: "@trpc/*"
groups:
sentry:
patterns:
- "@sentry/*"
prisma:
patterns:
- "prisma"
- "@prisma/*"
next:
patterns:
- "eslint-config-next"
- "next"
patches:
update-types:
- "patch"
- package-ecosystem: npm
directory: "/web" # Location of package manifests
schedule:
interval: "daily"
rebase-strategy: "disabled" # use dependabot-rebase-stale
+51 -15
View File
@@ -12,8 +12,15 @@ on:
branches:
- "main"
defaults:
run:
working-directory: web
jobs:
lint:
defaults:
run:
working-directory: .
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
@@ -21,37 +28,45 @@ jobs:
with:
node-version: 20
cache: "npm"
cache-dependency-path: "**/package-lock.json"
- name: install dependencies
run: |
npm ci
- name: Load default env
run: |
cp .env.dev.example .env
- name: lint
- name: lint web
working-directory: ./web
run: npm run lint
- name: lint worker
working-directory: ./worker
run: npm run lint
test-docker-build:
defaults:
run:
working-directory: web
runs-on: ubuntu-latest
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
steps:
- name: Setup node
uses: actions/setup-node@v3
with:
node-version: 20
- name: Checkout
uses: actions/checkout@v3
- name: Build Docker image
- name: Build Web Docker image
uses: docker/build-push-action@v4
with:
context: .
context: web
push: false
- name: Build Worker Docker image
uses: docker/build-push-action@v4
with:
context: worker
push: false
tests:
defaults:
run:
working-directory: web
runs-on: ubuntu-latest
strategy:
matrix:
@@ -68,19 +83,26 @@ jobs:
with:
node-version: ${{ matrix.node-version }}
cache: "npm"
cache-dependency-path: "**/package-lock.json"
- name: install dependencies
run: |
npm ci
- name: Load default env
working-directory: .
run: |
cp .env.dev.example .env
cp .env.dev.example web/.env
- name: Run, migrate, seed DB
- name: Run + migrate
working-directory: .
run: |
docker-compose -f docker-compose.dev.yml up -d
sleep 5 # Wait for PostgreSQL to accept connections
- name: Seed DB
run: |
npx --yes prisma migrate reset --force --skip-generate
- name: Build
@@ -93,6 +115,9 @@ jobs:
run: npm run test
e2e-tests:
defaults:
run:
working-directory: web
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
@@ -100,19 +125,26 @@ jobs:
with:
node-version: 20
cache: "npm"
cache-dependency-path: "**/package-lock.json"
- name: install dependencies
run: |
npm ci
- name: Load default env
working-directory: .
run: |
cp .env.dev.example .env
cp .env.dev.example web/.env
- name: Run, migrate, seed DB
- name: Run + migrate
working-directory: .
run: |
docker-compose -f docker-compose.dev.yml up -d
sleep 5 # Wait for PostgreSQL to accept connections
- name: Seed DB
run: |
npx --yes prisma migrate reset --force --skip-generate
- name: Build
@@ -133,9 +165,11 @@ jobs:
- name: Successful deploy
if: ${{ !(contains(needs.*.result, 'failure')) }}
run: exit 0
working-directory: .
- name: Failing deploy
if: ${{ contains(needs.*.result, 'failure') }}
run: exit 1
working-directory: .
push-docker-image:
needs: all-ci-passed
@@ -154,6 +188,7 @@ jobs:
uses: actions/setup-node@v3
with:
node-version: 20
cache-dependency-path: "**/package-lock.json"
- name: Checkout
uses: actions/checkout@v3
@@ -177,11 +212,12 @@ jobs:
type=sha
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
- name: Build and push Docker image
uses: docker/build-push-action@v4
with:
context: .
context: web
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
+2 -4
View File
@@ -21,13 +21,11 @@
"**/*.{cjs,mjs,ts,tsx,astro,md,mdx,json,yaml,yml}"
],
"mdx.experimentalLanguageServer": true,
"[astro]": {
"editor.defaultFormatter": "astro-build.astro-vscode"
},
"typescript.preferences.importModuleSpecifier": "non-relative",
"docwriter.style": "JSDoc",
"[prisma]": {
"editor.defaultFormatter": "Prisma.prisma"
},
"eslint.lintTask.enable": true
"eslint.lintTask.enable": true,
"eslint.workingDirectories": ["./web", "./worker"]
}
+29 -14
View File
@@ -91,9 +91,9 @@ flowchart TB
The diagram below may not show all relationships if the foreign key is not defined in the database schema. For instance, `trace_id` in the `observation` table is not defined as a foreign key to the `trace` table to allow unordered ingestion of these objects, but it is still a foreign key in the application code.
Full database schema: [prisma/schema.prisma](prisma/schema.prisma)
Full database schema: [web/prisma/schema.prisma](web/prisma/schema.prisma)
<img src="./prisma/database.svg">
<img src="./web/prisma/database.svg">
### Infrastructure & Network Overview
@@ -110,7 +110,14 @@ flowchart LR
App --- DB
```
## Development Setup
## Repository Structure
This repository contains the following packages:
- `web`: is the main application package providing Frontend and Backend APIs for Langfuse
- `worker` (no production yet): contains an application for asynchronous processing of tasks. This package is not yet used in production.
## Development Setup (web package only)
Requirements
@@ -120,25 +127,33 @@ Requirements
**Steps**
1. Fork the the repository and clone it locally
2. Install dependencies
2. Run the development database
```bash
npm install
npm run infra:dev:up
```
3. Run the development database
```bash
docker-compose -f docker-compose.dev.yml up -d
```
4. Create an env file
3. Create an env file
```bash
cp .env.dev.example .env
```
5. Run the migrations
4. CD into the web directory
```bash
cd web
```
5. Install dependencies
```bash
npm install
```
6. Run the migrations
The `schema.prisma` file is in the `web` directory and hence, migrations are applied from there.
```bash
npm run db:migrate
@@ -148,7 +163,7 @@ Requirements
# npm run db:seed:examples
```
6. Start the development server
7. Start the development server
```bash
npm run dev
+13 -11
View File
@@ -119,20 +119,22 @@ See our the [→ Quickstart](https://langfuse.com/docs/get-started) to get start
### Integrations
| Integration | Supports | Description |
| -------------------------------------------------------- | ------------- | ------------------------------------------------------------------------------- |
| [**SDK** - _recommended_](https://langfuse.com/docs/sdk) | Python, JS/TS | Manual instrumentation using the SDKs for full flexibility. |
| [OpenAI](https://langfuse.com/docs/openai) | Python | Automated instrumentation using drop-in replacement of OpenAI SDK. |
| [Langchain](https://langfuse.com/docs/langchain) | Python, JS/TS | Automated instrumentation by passing callback handler to Langchain application. |
| [API](https://langfuse.com/docs/api) | | Directly call the public API. OpenAPI spec available. |
| Integration | Supports | Description |
| ---------------------------------------------------------------- | ------------- | ---------------------------------------------------------------- |
| [**SDK** - _recommended_](https://langfuse.com/docs/sdk) | Python, JS/TS | Manual instrumentation using the SDKs for full flexibility. |
| [OpenAI SDK](https://langfuse.com/docs/integrations/openai) | Python | Automated instrumentation via drop-in replacement of OpenAI SDK. |
| [Langchain](https://langfuse.com/docs/integrations/langchain) | Python, JS/TS | Automated instrumentation via LlamaIndex callback system. |
| [LlamaIndex](https://langfuse.com/docs/integrations/llama-index) | Python, JS/TS | Automated instrumentation via LlamaIndex callback system. |
| [API](https://langfuse.com/docs/api) | | Directly call the public API. OpenAPI spec available. |
External projects/packages that integrate with Langfuse:
| Name | Description |
| ---------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| [LiteLLM](/https://langfuse.comdocs/litellm) | Use any LLM as a drop in replacement for GPT. Use Azure, OpenAI, Cohere, Anthropic, Ollama, VLLM, Sagemaker, HuggingFace, Replicate (100+ LLMs). |
| [Flowise](https://langfuse.com/docs/flowise) | JS/TS no-code builder for customized LLM flows. |
| [Langflow](https://langfuse.com/docs/langflow) | Python-based UI for LangChain, designed with react-flow to provide an effortless way to experiment and prototype flows. |
| Name | Description |
| --------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| [LiteLLM](https://langfuse.com/docs/integrations/litellm) | Use any LLM as a drop in replacement for GPT. Use Azure, OpenAI, Cohere, Anthropic, Ollama, VLLM, Sagemaker, HuggingFace, Replicate (100+ LLMs). |
| [Flowise](https://langfuse.com/docs/integrations/flowise) | JS/TS no-code builder for customized LLM flows. |
| [Langflow](https://langfuse.com/docs/integrations/langflow) | Python-based UI for LangChain, designed with react-flow to provide an effortless way to experiment and prototype flows. |
| [Superagent](https://langfuse.com/docs/integrations/superagent) | Open Source AI Assistant Framework & API for prototyping and deployment of agents. |
## Questions and feedback
+36 -2
View File
@@ -1,11 +1,13 @@
version: "3.5"
services:
langfuse-server:
server:
build:
dockerfile: Dockerfile
dockerfile: ./Dockerfile
context: ./web
depends_on:
- db
- redis
ports:
- "3000:3000"
environment:
@@ -16,8 +18,40 @@ services:
- TELEMETRY_ENABLED=${TELEMETRY_ENABLED:-true}
- NEXT_PUBLIC_SIGN_UP_DISABLED=${NEXT_PUBLIC_SIGN_UP_DISABLED:-false}
- LANGFUSE_ENABLE_EXPERIMENTAL_FEATURES=${LANGFUSE_ENABLE_EXPERIMENTAL_FEATURES:-false}
- REDIS_URL=${REDIS_URL:-redis}
- REDIS_PORT=${REDIS_PORT:-6379}
- REDIS_AUTH=${REDIS_AUTH:-myredissecret}
restart: always
worker:
build:
dockerfile: ./Dockerfile
context: ./worker
depends_on:
- db
- redis
- server
ports:
- "3030:3030"
environment:
- DATABASE_URL=postgresql://postgres:postgres@db:5432/postgres
- NEXTAUTH_SECRET=mysecret
- TELEMETRY_ENABLED=${TELEMETRY_ENABLED:-true}
- LANGFUSE_ENABLE_EXPERIMENTAL_FEATURES=${LANGFUSE_ENABLE_EXPERIMENTAL_FEATURES:-false}
- PORT=${PORT:-3030}
- REDIS_URL=${REDIS_URL:-redis}
- REDIS_PORT=${REDIS_PORT:-6379}
- REDIS_AUTH=${REDIS_AUTH:-myredissecret}
restart: always
redis:
image: redis
command: >
--requirepass ${REDIS_AUTH:-myredissecret}
restart: always
ports:
- 6379:6379
db:
image: postgres
restart: always
+6
View File
@@ -1,6 +1,12 @@
version: "3.5"
services:
redis:
image: redis
restart: always
ports:
- 6379:6379
db:
image: postgres
restart: always
+1 -1
View File
@@ -15,7 +15,7 @@ groups:
version: 0.0.26
output:
location: local-file-system
path: ../../../generated/openapi-client
path: ../../../web/generated/openapi-client
config:
namespaceExport: Langfuse
allowCustomFetcher: true
+21 -6
View File
@@ -90,14 +90,28 @@ types:
latency: optional<double>
Usage:
docs: Standard interface for usage and cost
properties:
input: optional<integer>
output: optional<integer>
total: optional<integer>
input:
docs: Number of input units (e.g. tokens)
type: optional<integer>
output:
docs: Number of output units (e.g. tokens)
type: optional<integer>
total:
docs: Defaults to input+output if not set
type: optional<integer>
unit: optional<ModelUsageUnit>
inputCost: optional<double>
outputCost: optional<double>
totalCost: optional<double>
inputCost:
docs: USD input cost
type: optional<double>
outputCost:
docs: USD output cost
type: optional<double>
totalCost:
docs: USD total cost, defaults to input+output
type: optional<double>
Score:
properties:
id: string
@@ -145,6 +159,7 @@ types:
# Utilities
ModelUsageUnit:
docs: Unit of usage in Langfuse
enum:
- CHARACTERS
- TOKENS
@@ -7,12 +7,12 @@ service:
endpoints:
create:
method: POST
docs: Create a dataset item, upserts on id
docs: Create a dataset item
path: /dataset-items
request: CreateDatasetItemRequest
response: commons.DatasetItem
get:
docs: Get a specific dataset item
docs: Get a dataset item
method: GET
path: /dataset-items/{id}
path-parameters:
@@ -26,4 +26,6 @@ types:
datasetName: string
input: unknown
expectedOutput: optional<unknown>
id: optional<string>
id:
type: optional<string>
docs: Dataset items are upserted on their id
+8 -3
View File
@@ -7,7 +7,7 @@ service:
base-path: /api/public
endpoints:
batch:
docs: Ingest multiple events to Langfuse
docs: Batched ingestion for Langfuse Tracing
method: POST
path: /ingestion
request:
@@ -31,8 +31,12 @@ types:
sdk-log: SDKLogEvent
# both are legacy
observation-create: CreateObservationEvent
observation-update: UpdateObservationEvent
observation-create:
type: CreateObservationEvent
docs: Deprecated event type
observation-update:
type: UpdateObservationEvent
docs: Deprecated event type
ObservationType:
enum:
@@ -47,6 +51,7 @@ types:
- OpenAIUsage
OpenAIUsage:
docs: Usage interface of OpenAI for improved compatibility.
properties:
promptTokens: optional<integer>
completionTokens: optional<integer>
+1 -1
View File
@@ -7,7 +7,7 @@ service:
base-path: /api/public
endpoints:
get:
docs: Get a specific observation
docs: Get a observation
method: GET
path: /observations/{observationId}
path-parameters:
+1
View File
@@ -7,6 +7,7 @@ service:
base-path: /api/public
endpoints:
get:
docs: Get Project associated with API key
method: GET
path: /projects
response: Projects
+5 -3
View File
@@ -7,7 +7,7 @@ service:
base-path: /api/public
endpoints:
get:
docs: Get a specific prompt
docs: Get a prompt
method: GET
path: /prompts
request:
@@ -17,7 +17,7 @@ service:
version: optional<integer>
response: Prompt
create:
docs: Create a specific prompt
docs: Create a prompt
method: POST
path: /prompts
request: CreatePromptRequest
@@ -27,7 +27,9 @@ types:
CreatePromptRequest:
properties:
name: string
isActive: boolean
isActive:
docs: Should the prompt be promoted to production immediately?
type: boolean
prompt: string
config: optional<unknown>
+11 -2
View File
@@ -7,13 +7,13 @@ service:
base-path: /api/public
endpoints:
create:
docs: Add a score to the database, upserts on id
docs: Create a score
method: POST
path: /scores
request: CreateScoreRequest
response: commons.Score
get:
docs: Get scores
docs: Get a list of scores
method: GET
path: /scores
request:
@@ -24,6 +24,15 @@ service:
userId: optional<string>
name: optional<string>
response: Scores
get-by-id:
docs: Get a score
method: GET
path: /scores/{scoreId}
path-parameters:
scoreId:
type: string
docs: The unique langfuse identifier of a score
response: commons.Score
delete:
docs: Delete a score
method: DELETE
+2 -2
View File
@@ -27,8 +27,8 @@ service:
userId: optional<string>
name: optional<string>
orderBy:
type: string
docs: Format of the string sort_by=timestamp.asc (id, timestamp, name, userId, release, version, public, bookmarked, sessionId)
type: optional<string>
docs: "Format of the string [field].[asc/desc]. Fields: id, timestamp, name, userId, release, version, public, bookmarked, sessionId. Example: timestamp.asc"
tags:
type: optional<string>
allow-multiple: true
+1 -1
View File
@@ -6,7 +6,7 @@ groups:
version: 0.0.28
output:
location: local-file-system
path: ../../../generated/openapi-server
path: ../../../web/generated/openapi-server
config:
namespaceExport: Langfuse
allowCustomFetcher: true
+42 -10
View File
@@ -46,7 +46,7 @@
"_type": "endpoint",
"name": "Create",
"request": {
"description": "Create a dataset item, upserts on id",
"description": "Create a dataset item",
"url": {
"raw": "{{baseUrl}}/api/public/dataset-items",
"host": [
@@ -79,7 +79,7 @@
"_type": "endpoint",
"name": "Get",
"request": {
"description": "Get a specific dataset item",
"description": "Get a dataset item",
"url": {
"raw": "{{baseUrl}}/api/public/dataset-items/:id",
"host": [
@@ -301,7 +301,7 @@
"_type": "endpoint",
"name": "Batch",
"request": {
"description": "Ingest multiple events to Langfuse",
"description": "Batched ingestion for Langfuse Tracing",
"url": {
"raw": "{{baseUrl}}/api/public/ingestion",
"host": [
@@ -400,7 +400,7 @@
"_type": "endpoint",
"name": "Get",
"request": {
"description": "Get a specific observation",
"description": "Get a observation",
"url": {
"raw": "{{baseUrl}}/api/public/observations/:observationId",
"host": [
@@ -500,7 +500,7 @@
"_type": "endpoint",
"name": "Get",
"request": {
"description": null,
"description": "Get Project associated with API key",
"url": {
"raw": "{{baseUrl}}/api/public/projects",
"host": [
@@ -532,7 +532,7 @@
"_type": "endpoint",
"name": "Get",
"request": {
"description": "Get a specific prompt",
"description": "Get a prompt",
"url": {
"raw": "{{baseUrl}}/api/public/prompts?name=&version=",
"host": [
@@ -568,7 +568,7 @@
"_type": "endpoint",
"name": "Create",
"request": {
"description": "Create a specific prompt",
"description": "Create a prompt",
"url": {
"raw": "{{baseUrl}}/api/public/prompts",
"host": [
@@ -608,7 +608,7 @@
"_type": "endpoint",
"name": "Create",
"request": {
"description": "Add a score to the database, upserts on id",
"description": "Create a score",
"url": {
"raw": "{{baseUrl}}/api/public/scores",
"host": [
@@ -641,7 +641,7 @@
"_type": "endpoint",
"name": "Get",
"request": {
"description": "Get scores",
"description": "Get a list of scores",
"url": {
"raw": "{{baseUrl}}/api/public/scores?page=&limit=&userId=&name=",
"host": [
@@ -683,6 +683,38 @@
},
"response": []
},
{
"_type": "endpoint",
"name": "Get By Id",
"request": {
"description": "Get a score",
"url": {
"raw": "{{baseUrl}}/api/public/scores/:scoreId",
"host": [
"{{baseUrl}}"
],
"path": [
"api",
"public",
"scores",
":scoreId"
],
"query": [],
"variable": [
{
"key": "scoreId",
"value": "",
"description": "The unique langfuse identifier of a score"
}
]
},
"header": [],
"method": "GET",
"auth": null,
"body": null
},
"response": []
},
{
"_type": "endpoint",
"name": "Delete",
@@ -832,7 +864,7 @@
{
"key": "orderBy",
"value": "",
"description": "Format of the string sort_by=timestamp.asc (id, timestamp, name, userId, release, version, public, bookmarked, sessionId)"
"description": "Format of the string [field].[asc/desc]. Fields: id, timestamp, name, userId, release, version, public, bookmarked, sessionId. Example: timestamp.asc"
},
{
"key": "tags",
+367 -17956
View File
File diff suppressed because it is too large Load Diff
+11 -167
View File
@@ -1,178 +1,22 @@
{
"name": "langfuse-core",
"name": "langfuse",
"version": "2.7.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",
"build": "next build",
"dev": "next dev",
"dx": "npm i && npm run db:reset && npm run db:seed:examples && npm run dev",
"postinstall": "prisma generate",
"lint": "next lint",
"lint:fix": "next lint --fix",
"prettier": "prettier --write ./src *.{ts,js}",
"clean": "rm -rf node_modules",
"start": "next start",
"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",
"db:seed:examples": "npx prisma db seed -- --environment examples",
"release": "release-it",
"models:migrate": "tsx scripts/model-match.ts"
},
"prisma": {
"seed": "ts-node -r tsconfig-paths/register --compiler-options {\"module\":\"CommonJS\"} prisma/seed.ts"
},
"dependencies": {
"@anthropic-ai/tokenizer": "^0.0.4",
"@aws-sdk/client-s3": "^3.507.0",
"@aws-sdk/lib-storage": "^3.511.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.9.1",
"@radix-ui/react-accordion": "^1.1.2",
"@radix-ui/react-alert-dialog": "^1.0.5",
"@radix-ui/react-avatar": "^1.0.4",
"@radix-ui/react-checkbox": "^1.0.4",
"@radix-ui/react-collapsible": "^1.0.3",
"@radix-ui/react-dialog": "^1.0.5",
"@radix-ui/react-dropdown-menu": "^2.0.6",
"@radix-ui/react-hover-card": "^1.0.7",
"@radix-ui/react-icons": "^1.3.0",
"@radix-ui/react-label": "^2.0.2",
"@radix-ui/react-popover": "^1.0.7",
"@radix-ui/react-scroll-area": "^1.0.5",
"@radix-ui/react-select": "^2.0.0",
"@radix-ui/react-separator": "^1.0.3",
"@radix-ui/react-slider": "^1.1.2",
"@radix-ui/react-slot": "^1.0.2",
"@radix-ui/react-switch": "^1.0.3",
"@radix-ui/react-tabs": "^1.0.4",
"@radix-ui/react-toggle": "^1.0.3",
"@radix-ui/react-tooltip": "^1.0.7",
"@react-email/components": "^0.0.14",
"@react-email/render": "^0.0.12",
"@sentry/nextjs": "^7.101.1",
"@sentry/profiling-node": "^7.101.1",
"@sentry/types": "^7.88.0",
"@t3-oss/env-nextjs": "^0.8.0",
"@tailwindcss/forms": "^0.5.7",
"@tanstack/react-query": "^4.36.1",
"@tanstack/react-table": "^8.11.8",
"@tremor/react": "^3.11.1",
"@trpc/client": "^10.45.0",
"@trpc/next": "^10.45.0",
"@trpc/react-query": "^10.45.0",
"@trpc/server": "^10.45.0",
"bcryptjs": "^2.4.3",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.0",
"cmdk": "^0.2.1",
"core-js": "^3.36.0",
"cors": "^2.8.5",
"date-fns": "^3.3.1",
"decimal.js": "^10.4.3",
"exponential-backoff": "^3.1.1",
"js-tiktoken": "^1.0.10",
"kysely": "^0.27.2",
"lodash": "^4.17.21",
"lucide-react": "^0.330.0",
"next": "^14.1.0",
"next-auth": "^4.24.6",
"next-query-params": "^5.0.0",
"nodemailer": "^6.9.9",
"posthog-js": "^1.105.9",
"posthog-node": "^3.6.3",
"prisma-kysely": "^1.8.0",
"react": "18.2.0",
"react-day-picker": "^8.10.0",
"react-dom": "18.2.0",
"react-hook-form": "^7.50.1",
"react-icons": "^5.0.1",
"react-responsive": "^9.0.2",
"react18-json-view": "^0.2.7",
"sonner": "^1.4.0",
"superjson": "2.2.1",
"tailwind-merge": "^2.2.1",
"tailwindcss-animate": "^1.0.7",
"use-query-params": "^2.2.1",
"uuid": "^9.0.1",
"zod": "^3.22.4"
"infra:dev:up": "docker-compose -f ./docker-compose.dev.yml up -d",
"infra:dev:down": "docker-compose -f ./docker-compose.dev.yml down",
"dev": "npm run dev --prefix worker/ & npm run dev --prefix web/",
"postinstall": "cd worker && npm install && cd ../web && npm install",
"dx": "dotenv -e .env -- npm i && npm run infra:dev:up && cd web && npm run db:reset && npm run db:seed:examples && cd .. && npm run dev"
},
"author": "",
"license": "MIT",
"devDependencies": {
"@jedmao/location": "^3.0.0",
"@mermaid-js/mermaid-cli": "^10.7.0",
"@playwright/test": "^1.41.2",
"@release-it/bumper": "^6.0.1",
"@testing-library/jest-dom": "^6.4.2",
"@testing-library/react": "^14.2.1",
"@types/bcryptjs": "^2.4.6",
"@types/cors": "^2.8.17",
"@types/eslint": "^8.56.2",
"@types/jest": "^29.5.12",
"@types/lodash": "^4.14.202",
"@types/node": "20.10.5",
"@types/nodemailer": "^6.4.14",
"@types/react": "^18.2.55",
"@types/react-dom": "^18.2.19",
"@types/uuid": "^9.0.8",
"@typescript-eslint/eslint-plugin": "^6.21.0",
"@typescript-eslint/parser": "^6.21.0",
"autoprefixer": "^10.4.17",
"@typescript-eslint/eslint-plugin": "^7.0.2",
"@typescript-eslint/parser": "^7.0.2",
"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.35",
"prettier": "^3.2.5",
"prettier-plugin-tailwindcss": "^0.5.11",
"prisma": "^5.9.1",
"prisma-erd-generator": "^1.11.2",
"release-it": "^17.0.5",
"tailwindcss": "^3.4.1",
"ts-node": "^10.9.2",
"tsconfig-paths": "^4.2.0",
"tsx": "^4.7.1",
"typescript": "^5.3.3"
},
"ct3aMetadata": {
"initVersion": "7.13.0"
},
"optionalDependencies": {
"crisp-sdk-web": "^1.0.21"
},
"release-it": {
"git": {
"commitMessage": "chore: release v${version}",
"tagName": "v${version}"
},
"github": {
"release": true,
"web": true,
"autoGenerate": true,
"releaseName": "v${version}",
"comments": {
"submit": true,
"issue": ":rocket: _This issue has been resolved in v${version}. See [${releaseName}](${releaseUrl}) for release notes._",
"pr": ":rocket: _This pull request is included in v${version}. See [${releaseName}](${releaseUrl}) for release notes._"
}
},
"plugins": {
"@release-it/bumper": {
"out": {
"file": "./src/constants/VERSION.ts",
"type": "application/typescript"
}
}
}
"prettier": "^3.2.5"
}
}
-617
View File
@@ -1,617 +0,0 @@
import { PrismaClient } from "@prisma/client";
import {
hashSecretKey,
getDisplaySecretKey,
} 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" },
} as const;
const prisma = new PrismaClient();
const TRACE_VOLUME = 100;
async function main() {
const environment = parseArgs({
options,
}).values.environment;
const user = await prisma.user.upsert({
where: { id: "user-1" },
update: {
name: "Demo User",
email: "demo@langfuse.com",
password: await hash("password", 12),
},
create: {
id: "user-1",
name: "Demo User",
email: "demo@langfuse.com",
password: await hash("password", 12),
},
});
const seedProjectId = "7a88fb47-b4e2-43b8-a06c-a5ce950dc53a";
const project1 = await prisma.project.upsert({
where: { id: seedProjectId },
update: {
name: "llm-app",
},
create: {
id: seedProjectId,
name: "llm-app",
members: {
create: {
role: "OWNER",
userId: user.id,
},
},
},
});
const prompt = await prisma.prompt.upsert({
where: {
projectId_name_version: {
projectId: seedProjectId,
name: "summary-prompt",
version: 1,
},
},
create: {
name: "summary-prompt",
project: { connect: { id: seedProjectId } },
prompt: "prompt {{variable}} {{anotherVariable}}",
isActive: true,
version: 1,
createdBy: "user-1",
},
update: {},
});
const seedApiKey = {
id: "seed-api-key",
secret: process.env.SEED_SECRET_KEY ?? "sk-lf-1234567890",
public: "pk-lf-1234567890",
note: "seeded key",
};
if (!(await prisma.apiKey.findUnique({ where: { id: seedApiKey.id } }))) {
await prisma.apiKey.create({
data: {
note: seedApiKey.note,
id: seedApiKey.id,
publicKey: seedApiKey.public,
hashedSecretKey: await hashSecretKey(seedApiKey.secret),
displaySecretKey: getDisplaySecretKey(seedApiKey.secret),
project: {
connect: {
id: project1.id,
},
},
},
});
}
// Do not run the following for local docker compose setup
if (environment === "examples") {
const project2 = await prisma.project.upsert({
where: { id: "239ad00f-562f-411d-af14-831c75ddd875" },
create: {
name: "demo-app",
apiKeys: {
create: [
{
note: "seeded key",
hashedSecretKey: await hashSecretKey("sk-lf-asdfghjkl"),
displaySecretKey: getDisplaySecretKey("sk-lf-asdfghjkl"),
publicKey: "pk-lf-asdfghjkl",
},
],
},
members: {
create: {
role: "OWNER",
userId: user.id,
},
},
},
update: {},
});
const promptIds: string[] = [];
const prompts = [
{
id: `prompt-${Math.floor(Math.random() * 1000000000)}`,
projectId: project2.id,
createdBy: "user-1",
prompt: "Prompt 1 content",
name: "Prompt 1",
version: 1,
isActive: true,
},
{
id: `prompt-${Math.floor(Math.random() * 1000000000)}`,
projectId: project2.id,
createdBy: "user-1",
prompt: "Prompt 2 content",
name: "Prompt 2",
version: 1,
isActive: true,
},
{
id: `prompt-${Math.floor(Math.random() * 1000000000)}`,
projectId: project2.id,
createdBy: "API",
prompt: "Prompt 3 content",
name: "Prompt 3 by API",
version: 1,
isActive: true,
},
];
for (const prompt of prompts) {
await prisma.prompt.create({
data: {
id: prompt.id,
projectId: prompt.projectId,
createdBy: prompt.createdBy,
prompt: prompt.prompt,
name: prompt.name,
version: prompt.version,
isActive: prompt.isActive,
},
});
promptIds.push(prompt.id);
}
const promptVersionsWithVariables = [
{
id: `prompt-${Math.floor(Math.random() * 1000000000)}`,
projectId: project2.id,
createdBy: "user-1",
prompt: "Prompt 4 version 1 content with {{variable}}",
name: "Prompt 4 with variable and config",
config: {
temperature: 0.7,
},
version: 1,
isActive: false,
},
{
id: `prompt-${Math.floor(Math.random() * 1000000000)}`,
projectId: project2.id,
createdBy: "user-1",
prompt: "Prompt 4 version 2 content with {{variable}}",
name: "Prompt 4 with variable and config",
config: {
temperature: 0.7,
topP: 0.9,
},
version: 2,
isActive: true,
},
{
id: `prompt-${Math.floor(Math.random() * 1000000000)}`,
projectId: project2.id,
createdBy: "user-1",
prompt: "Prompt 4 version 3 content with {{variable}}",
name: "Prompt 4 with variable and config",
config: {
temperature: 0.7,
topP: 0.9,
frequencyPenalty: 0.5,
},
version: 3,
isActive: false,
},
];
for (const version of promptVersionsWithVariables) {
await prisma.prompt.create({
data: {
id: version.id,
projectId: version.projectId,
createdBy: version.createdBy,
prompt: version.prompt,
name: version.name,
config: version.config,
version: version.version,
isActive: version.isActive,
},
});
promptIds.push(version.id);
}
const promptName = "Prompt with many versions";
const projectId = project2.id;
const createdBy = "user-1";
for (let i = 1; i <= 20; i++) {
const promptId = `prompt-${Math.floor(Math.random() * 1000000000)}`;
await prisma.prompt.create({
data: {
id: promptId,
projectId: projectId,
createdBy: createdBy,
prompt: `${promptName} version ${i} content`,
name: promptName,
version: i,
isActive: i === 20,
},
});
promptIds.push(promptId);
}
const generationIds: string[] = [];
const envTags = [null, "development", "staging", "production"];
const colorTags = [null, "red", "blue", "yellow"];
for (let i = 0; i < TRACE_VOLUME; i++) {
// print progress to console with a progress bar that refreshes every 10 iterations
if ((i + 1) % 10 === 0 || i === TRACE_VOLUME - 1) {
process.stdout.clearLine(0);
process.stdout.cursorTo(0);
process.stdout.write(`Seeding ${i + 1} of ${TRACE_VOLUME}`);
}
// random date within last 90 days, with a linear bias towards more recent dates
const traceTs = new Date(
Date.now() -
Math.floor(Math.random() ** 1.5 * 90 * 24 * 60 * 60 * 1000),
);
const envTag = envTags[Math.floor(Math.random() * envTags.length)];
const colorTag = colorTags[Math.floor(Math.random() * colorTags.length)];
const tags = [envTag, colorTag].filter((tag) => tag !== null);
const projectId = [project1.id, project2.id][i % 2] as string;
const trace = await prisma.trace.create({
data: {
id: `trace-${Math.floor(Math.random() * 1000000000)}`,
timestamp: traceTs,
name: ["generate-outreach", "label-inbound", "draft-response"][
i % 3
] as string,
metadata: {
user: `user-${i}@langfuse.com`,
more: "1,2,3;4?6",
},
tags: tags as string[],
project: {
connect: { id: projectId },
},
userId: `user-${i % 10}`,
session:
Math.random() > 0.3
? {
connectOrCreate: {
where: {
id_projectId: {
id: `session-${i % 10}`,
projectId: projectId,
},
},
create: {
id: `session-${i % 10}`,
projectId: projectId,
},
},
}
: undefined,
input:
Math.random() > 0.3
? "I'm looking for a React component"
: undefined,
output:
Math.random() > 0.3
? "What kind of component are you looking for?"
: undefined,
scores: {
createMany: {
data: [
...(Math.random() > 0.5
? [
{
name: "feedback",
value: Math.floor(Math.random() * 3) - 1,
timestamp: traceTs,
},
]
: []),
...(Math.random() > 0.7
? [
{
name: "sentiment",
value: Math.floor(Math.random() * 10) - 5,
timestamp: traceTs,
},
]
: []),
],
},
},
},
});
const existingSpanIds: string[] = [];
for (let j = 0; j < Math.floor(Math.random() * 10) + 1; j++) {
// add between 1 and 30 ms to trace timestamp
const spanTsStart = new Date(
traceTs.getTime() + Math.floor(Math.random() * 30),
);
// random duration of upto 30ms
const spanTsEnd = new Date(
spanTsStart.getTime() + Math.floor(Math.random() * 30),
);
const span = await prisma.observation.create({
data: {
type: "SPAN",
id: `span-${Math.floor(Math.random() * 1000000000)}`,
startTime: spanTsStart,
endTime: spanTsEnd,
name: `span-${i}-${j}`,
metadata: {
user: `user-${i}@langfuse.com`,
},
project: { connect: { id: trace.projectId } },
traceId: trace.id,
// if this is the first span or in 50% of cases, add no parent; otherwise randomly select parent from existing spans
...(existingSpanIds.length === 0 || Math.random() > 0.5
? {}
: {
parentObservationId:
existingSpanIds[
Math.floor(Math.random() * existingSpanIds.length)
],
}),
},
});
existingSpanIds.push(span.id);
for (let k = 0; k < Math.floor(Math.random() * 2) + 1; k++) {
// random start and end times within span
const generationTsStart = new Date(
spanTsStart.getTime() +
Math.floor(
Math.random() * (spanTsEnd.getTime() - spanTsStart.getTime()),
),
);
const generationTsEnd = new Date(
generationTsStart.getTime() +
Math.floor(
Math.random() *
(spanTsEnd.getTime() - generationTsStart.getTime()),
),
);
const promptTokens = Math.floor(Math.random() * 1000) + 300;
const completionTokens = Math.floor(Math.random() * 500) + 100;
const models = [
"gpt-3.5-turbo",
"gpt-4",
"gpt-4-32k-0613",
"gpt-3.5-turbo-16k-0613",
"claude-instant-1",
"claude-2.1",
"gpt-4-vision-preview",
"MIXTRAL-8X7B",
];
const model = models[Math.floor(Math.random() * models.length)];
const promptId =
promptIds[Math.floor(Math.random() * promptIds.length)];
const generation = await prisma.observation.create({
data: {
type: "GENERATION",
id: `generation-${Math.floor(Math.random() * 1000000000)}`,
startTime: generationTsStart,
endTime: generationTsEnd,
name: `generation-${i}-${j}-${k}`,
project: { connect: { id: trace.projectId } },
prompt: { connect: { id: promptId } },
input:
Math.random() > 0.5
? [
{
role: "system",
content: "Be a helpful assistant",
},
{
role: "user",
content: "How can i create a React component?",
},
]
: {
input: "How can i create a React component?",
retrievedDocuments: [
{
title: "How to create a React component",
url: "https://www.google.com",
description: "A guide to creating React components",
},
{
title: "React component creation",
url: "https://www.google.com",
description: "A guide to creating React components",
},
],
},
output: {
completion: `Creating a React component can be done in two ways: as a functional component or as a class component. Let's start with a basic example of both.
1. **Functional Component**:
A functional component is just a plain JavaScript function that accepts props as an argument, and returns a React element. Here's how you can create one:
'import React from 'react'; function Greeting(props) { return <h1>Hello, {props.name}</h1>; } export default Greeting;'
To use this component in another file, you can do:
'import Greeting from './Greeting'; function App() { return ( <div> <Greeting name="John" /> </div> ); } export default App;'
2. **Class Component**:
You can also define components as classes in React. These have some additional features compared to functional components:
'import React, { Component } from 'react'; class Greeting extends Component { render() { return <h1>Hello, {this.props.name}</h1>; } } export default Greeting;'
And here's how to use this component:
'import Greeting from './Greeting'; class App extends Component { render() { return ( <div> <Greeting name="John" /> </div> ); } } export default App;'
With the advent of hooks in React, functional components can do everything that class components can do and hence, the community has been favoring functional components over class components.
Remember to import React at the top of your file whenever you're creating a component, because JSX transpiles to 'React.createElement' calls under the hood.`,
},
model: model,
internalModel: model,
modelParameters: {
temperature:
Math.random() > 0.9 ? undefined : Math.random().toFixed(2),
topP:
Math.random() > 0.9 ? undefined : Math.random().toFixed(2),
maxTokens:
Math.random() > 0.9
? undefined
: Math.floor(Math.random() * 1000),
},
metadata: {
user: `user-${i}@langfuse.com`,
},
promptTokens,
completionTokens,
totalTokens: promptTokens + completionTokens,
parentObservationId: span.id,
traceId: trace.id,
...{
...(Math.random() > 0.5 && trace.projectId === prompt.projectId
? { prompt: { connect: { id: prompt.id } } }
: {}),
},
unit: ModelUsageUnit.Tokens,
},
});
if (Math.random() > 0.6)
await prisma.score.create({
data: {
name: "quality",
value: Math.random() * 2 - 1,
observationId: generation.id,
traceId: trace.id,
},
});
if (Math.random() > 0.6)
await prisma.score.create({
data: {
name: "conciseness",
value: Math.random() * 2 - 1,
observationId: generation.id,
traceId: trace.id,
},
});
generationIds.push(generation.id);
for (let l = 0; l < Math.floor(Math.random() * 2); l++) {
// random start time within span
const eventTs = new Date(
spanTsStart.getTime() +
Math.floor(
Math.random() * (spanTsEnd.getTime() - spanTsStart.getTime()),
),
);
await prisma.observation.create({
data: {
type: "EVENT",
id: `event-${Math.floor(Math.random() * 1000000000)}`,
startTime: eventTs,
name: `event-${i}-${j}-${k}-${l}`,
metadata: {
user: `user-${i}@langfuse.com`,
},
parentObservationId: span.id,
traceId: trace.id,
project: { connect: { id: trace.projectId } },
},
});
}
}
}
}
for (let datasetNumber = 0; datasetNumber < 2; datasetNumber++) {
const dataset = await prisma.dataset.create({
data: {
name: `demo-dataset-${datasetNumber}`,
projectId: project2.id,
},
});
for (let datasetRunNumber = 0; datasetRunNumber < 2; datasetRunNumber++) {
const datasetRun = await prisma.datasetRuns.create({
data: {
name: `demo-dataset-run-${datasetRunNumber}`,
datasetId: dataset.id,
},
});
for (let runNumber = 0; runNumber < 10; runNumber++) {
//pick randomly from existingSpanIds
const sourceObservationId =
generationIds[Math.floor(Math.random() * generationIds.length)];
const runObservationId =
generationIds[Math.floor(Math.random() * generationIds.length)];
const datasetItem = await prisma.datasetItem.create({
data: {
datasetId: dataset.id,
sourceObservationId:
Math.random() > 0.5 ? sourceObservationId : undefined,
input: [
{
role: "user",
content: "How can i create a React component?",
},
],
expectedOutput:
"Creating a React component can be done in two ways: as a functional component or as a class component. Let's start with a basic example of both.",
},
});
await prisma.datasetRunItems.create({
data: {
datasetItemId: datasetItem.id,
observationId: runObservationId!,
datasetRunId: datasetRun.id,
},
});
}
}
}
}
}
main()
.then(async () => {
await prisma.$disconnect();
})
.catch(async (e) => {
console.error(e);
await prisma.$disconnect();
process.exit(1);
});
Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 772 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 312 KiB

-84
View File
@@ -1,84 +0,0 @@
import { TrashIcon } from "lucide-react";
import { useRouter } from "next/router";
import { useState } from "react";
import { Button } from "@/src/components/ui/button";
import { api } from "@/src/utils/api";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/src/components/ui/popover";
import { useHasAccess } from "@/src/features/rbac/utils/checkAccess";
import { usePostHog } from "posthog-js/react";
export function DeleteTrace({
traceId,
projectId,
isTableAction,
}: {
traceId: string;
projectId: string;
isTableAction?: boolean;
}) {
const [isDeleted, setIsDeleted] = useState(false);
const router = useRouter();
const utils = api.useUtils();
const posthog = usePostHog();
const hasAccess = useHasAccess({ projectId, scope: "traces:delete" });
const mutDeleteTraces = api.traces.deleteMany.useMutation({
onSuccess: () => {
setIsDeleted(true);
void utils.traces.invalidate();
if (!isTableAction) {
void router.push(`/project/${projectId}/traces`);
}
},
});
if (!hasAccess) {
return null;
}
return (
<Popover key={traceId}>
<PopoverTrigger asChild>
{isTableAction ? (
<Button variant="ghost" size="xs">
<TrashIcon className="h-4 w-4" />
</Button>
) : (
<Button variant="outline" type="button" size="icon">
<TrashIcon className="h-4 w-4" />
</Button>
)}
</PopoverTrigger>
<PopoverContent>
<h2 className="text-md mb-3 font-semibold">Please confirm</h2>
<p className="mb-3 text-sm">
This action cannot be undone and removes all the data associated with
this trace.
</p>
<div className="flex justify-end space-x-4">
<Button
type="button"
variant="destructive"
loading={mutDeleteTraces.isLoading || isDeleted}
onClick={() => {
void mutDeleteTraces.mutateAsync({
traceIds: [traceId],
projectId,
});
posthog.capture("trace:delete", {
source: isTableAction ? "table-single-row" : "trace",
});
}}
>
Delete trace
</Button>
</div>
</PopoverContent>
</Popover>
);
}
-1
View File
@@ -1 +0,0 @@
export const VERSION = "v2.7.0";
@@ -1,52 +0,0 @@
import { Button } from "@/src/components/ui/button";
import { LockIcon, PlusIcon } from "lucide-react";
import {
Dialog,
DialogContent,
DialogHeader,
DialogTitle,
} from "@/src/components/ui/dialog";
import { useState } from "react";
import { DialogTrigger } from "@radix-ui/react-dialog";
import { NewDatasetForm } from "@/src/features/datasets/components/NewDatasetForm";
import { useHasAccess } from "@/src/features/rbac/utils/checkAccess";
export const NewDatasetButton = (props: {
projectId: string;
datasetId?: string;
className?: string;
}) => {
const [open, setOpen] = useState(false);
const hasAccess = useHasAccess({
projectId: props.projectId,
scope: "datasets:CUD",
});
return (
<Dialog open={hasAccess && open} onOpenChange={setOpen}>
<DialogTrigger asChild>
<Button
variant="secondary"
className={props.className}
disabled={!hasAccess}
>
{hasAccess ? (
<PlusIcon className="-ml-0.5 mr-1.5" aria-hidden="true" />
) : (
<LockIcon className="-ml-0.5 mr-1.5 h-3 w-3" aria-hidden="true" />
)}
New dataset
</Button>
</DialogTrigger>
<DialogContent className="sm:max-w-3xl">
<DialogHeader>
<DialogTitle className="mb-5">Create new dataset</DialogTitle>
</DialogHeader>
<NewDatasetForm
projectId={props.projectId}
onFormSuccess={() => setOpen(false)}
/>
</DialogContent>
</Dialog>
);
};
@@ -1,94 +0,0 @@
import { Button } from "@/src/components/ui/button";
import * as z from "zod";
import { zodResolver } from "@hookform/resolvers/zod";
import { useForm } from "react-hook-form";
import {
Form,
FormControl,
FormField,
FormItem,
FormLabel,
FormMessage,
} from "@/src/components/ui/form";
import { api } from "@/src/utils/api";
import { useState } from "react";
import { usePostHog } from "posthog-js/react";
import { Input } from "@/src/components/ui/input";
const formSchema = z.object({
name: z.string(),
});
export const NewDatasetForm = (props: {
projectId: string;
onFormSuccess?: () => void;
}) => {
const [formError, setFormError] = useState<string | null>(null);
const posthog = usePostHog();
const form = useForm<z.infer<typeof formSchema>>({
resolver: zodResolver(formSchema),
defaultValues: {
name: "",
},
});
const utils = api.useUtils();
const createDatasetMutation = api.datasets.createDataset.useMutation({
onSuccess: () => utils.datasets.invalidate(),
onError: (error) => setFormError(error.message),
});
function onSubmit(values: z.infer<typeof formSchema>) {
posthog.capture("datasets:new_dataset_form_submit");
createDatasetMutation
.mutateAsync({
...values,
projectId: props.projectId,
})
.then(() => {
props.onFormSuccess?.();
form.reset();
})
.catch((error) => {
console.error(error);
});
}
return (
<div>
<Form {...form}>
<form
// eslint-disable-next-line @typescript-eslint/no-misused-promises
onSubmit={form.handleSubmit(onSubmit)}
className="space-y-8"
>
<FormField
control={form.control}
name="name"
render={({ field }) => (
<FormItem>
<FormLabel>Name</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<Button
type="submit"
loading={createDatasetMutation.isLoading}
className="w-full"
>
New dataset
</Button>
</form>
</Form>
{formError ? (
<p className="text-red text-center">
<span className="font-bold">Error:</span> {formError}
</p>
) : null}
</div>
);
};
-78
View File
@@ -1,78 +0,0 @@
import { prisma } from "@/src/server/db";
import { type NextApiRequest, type NextApiResponse } from "next";
import { z } from "zod";
import { cors, runMiddleware } from "@/src/features/public-api/server/cors";
import { verifyAuthHeaderAndReturnScope } from "@/src/features/public-api/server/apiAuth";
const ScoreDeleteSchema = z.object({
scoreId: z.string(),
});
export default async function handler(
req: NextApiRequest,
res: NextApiResponse,
) {
await runMiddleware(req, res, cors);
// CHECK AUTH
const authCheck = await verifyAuthHeaderAndReturnScope(
req.headers.authorization,
);
if (!authCheck.validKey)
return res.status(401).json({
message: authCheck.error,
});
// END CHECK AUTH
if (req.method === "DELETE") {
try {
if (authCheck.scope.accessLevel !== "all") {
return res.status(401).json({
message:
"Access denied - need to use basic auth with secret key to DELETE scores",
});
}
const { scoreId } = ScoreDeleteSchema.parse(req.query); // uses query and not body
const score = await prisma.score.findUnique({
select: {
id: true,
},
where: {
id: scoreId,
trace: {
projectId: authCheck.scope.projectId,
},
},
});
if (!score) {
return res.status(404).json({
message: "Score not found within authorized project",
});
}
await prisma.score.delete({
where: {
id: scoreId,
trace: {
projectId: authCheck.scope.projectId,
},
},
});
return res.status(200).json({ message: "Score deleted successfully" });
} catch (error: unknown) {
console.error(error);
const errorMessage =
error instanceof Error ? error.message : "An unknown error occurred";
res.status(400).json({
message: "Invalid request data",
error: errorMessage,
});
}
} else {
return res.status(405).json({ message: "Method not allowed" });
}
}
@@ -1,59 +0,0 @@
import { Transform, type TransformCallback } from "stream";
import { usdFormatter } from "@/src/utils/numbers";
import type { ObservationView } from "@prisma/client";
export function transformStreamToCsv(): Transform {
let isFirstChunk = true;
return new Transform({
objectMode: true,
transform(
row: ObservationView,
encoding: BufferEncoding,
callback: TransformCallback,
): void {
if (isFirstChunk) {
// Output the header if it's the first chunk
const csvHeader = [
"traceId",
"name",
"model",
"startTime",
"endTime",
"cost",
"prompt",
"completion",
"metadata",
];
this.push(csvHeader.join(",") + "\n");
isFirstChunk = false;
}
// Convert the generation object to a CSV line and push it
const csvRow = [
row.traceId,
row.name ?? "",
row.model ?? "",
row.startTime.toISOString(),
row.endTime?.toISOString() ?? "",
row.calculatedTotalCost
? usdFormatter(row.calculatedTotalCost.toNumber(), 2, 8)
: "",
JSON.stringify(row.input),
JSON.stringify(row.output),
JSON.stringify(row.metadata),
].map((field) => {
const str = typeof field === "string" ? field : String(field);
return `"${str.replace(/"/g, '""')}"`;
});
this.push(csvRow.join(",") + "\n");
callback();
},
});
}
-8
View File
@@ -1,8 +0,0 @@
export class ResourceNotFoundError extends Error {
id: string;
constructor(type: string, id: string) {
super(`${type} with ${id} not found}`);
this.name = "ResourceNotFoundError";
this.id = id;
}
}
+7
View File
@@ -0,0 +1,7 @@
Dockerfile
.dockerignore
node_modules
npm-debug.log
README.md
.next
.git
+1 -1
View File
@@ -44,4 +44,4 @@ const config = {
},
};
module.exports = config;
module.exports = config;
+55
View File
@@ -0,0 +1,55 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# database
/prisma/db.sqlite
/prisma/db.sqlite-journal
# next.js
/.next/
/out/
next-env.d.ts
# production
/build
# idea
.idea
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*
# local env files
# do not commit any .env files to git, except for the .env.example file. https://create.t3.gg/en/usage/env-variables#using-environment-variables
.env
.env.local
.env*.local
# vercel
.vercel
# typescript
*.tsbuildinfo
/generated/typescript-server
# openapi spec that is copied during build
/public/openapi*.yml
# vscode
.devcontainer
View File
View File
+104
View File
@@ -0,0 +1,104 @@
openapi: 3.0.1
info:
title: langfuse
version: ''
paths:
/api/public/scores:
post:
description: Add a score to the database, upserts on id
operationId: score_create
tags:
- Score
parameters: []
responses:
'200':
description: ''
content:
application/json:
schema:
$ref: '#/components/schemas/Score'
'400':
description: ''
content:
application/json:
schema:
type: string
'401':
description: ''
content:
application/json:
schema:
type: string
'403':
description: ''
content:
application/json:
schema:
type: string
'405':
description: ''
content:
application/json:
schema:
type: string
security:
- BearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateScoreRequest'
components:
schemas:
CreateScoreRequest:
title: CreateScoreRequest
type: object
properties:
id:
type: string
traceId:
type: string
name:
type: string
value:
type: number
format: double
observationId:
type: string
comment:
type: string
required:
- traceId
- name
- value
Score:
title: Score
type: object
properties:
id:
type: string
traceId:
type: string
name:
type: string
value:
type: number
format: double
observationId:
type: string
timestamp:
type: string
format: date-time
comment:
type: string
required:
- id
- traceId
- name
- value
- timestamp
securitySchemes:
BearerAuth:
type: http
scheme: bearer
File diff suppressed because it is too large Load Diff
+20 -20
View File
@@ -34,26 +34,26 @@ const nextConfig = {
],
},
// Required to check authentication status from langfuse.com
...(env.NEXT_PUBLIC_LANGFUSE_CLOUD_REGION !== undefined ?
[
{
source: "/api/auth/session",
headers: [
{
key: "Access-Control-Allow-Origin",
value: "https://langfuse.com",
},
{ key: "Access-Control-Allow-Credentials", value: "true" },
{ key: "Access-Control-Allow-Methods", value: "GET,POST" },
{
key: "Access-Control-Allow-Headers",
value: "Content-Type, Authorization",
},
]
},
] : []
)
]
...(env.NEXT_PUBLIC_LANGFUSE_CLOUD_REGION !== undefined
? [
{
source: "/api/auth/session",
headers: [
{
key: "Access-Control-Allow-Origin",
value: "https://langfuse.com",
},
{ key: "Access-Control-Allow-Credentials", value: "true" },
{ key: "Access-Control-Allow-Methods", value: "GET,POST" },
{
key: "Access-Control-Allow-Headers",
value: "Content-Type, Authorization",
},
],
},
]
: []),
];
},
// webassembly support for @dqbd/tiktoken
+19977
View File
File diff suppressed because it is too large Load Diff
+180
View File
@@ -0,0 +1,180 @@
{
"name": "langfuse-core",
"version": "2.10.3",
"private": true,
"scripts": {
"prebuild": "cp generated/openapi-client/openapi.yml public/openapi-client.yml && cp generated/openapi-server/openapi.yml public/openapi-server.yml",
"build": "next build",
"dev": "dotenv -e ../.env -- next dev",
"dx": "dotenv -e ../.env -- npm i && npm run db:reset && npm run db:seed:examples && npm run dev",
"postinstall": "dotenv -e ../.env -- prisma generate",
"lint": "dotenv -e ../.env -- next lint",
"lint:fix": "dotenv -e ../.env -- next lint --fix",
"prettier": "prettier --write ./src *.{ts,js}",
"clean": "rm -rf node_modules",
"start": "next start",
"test": "dotenv -e ../.env -- jest --runInBand",
"test:watch": "dotenv -e ../.env -- jest --watch --runInBand",
"test:e2e": "dotenv -e ../.env -- playwright test",
"db:migrate": "DISABLE_ERD=false dotenv -e ../.env -- npx prisma migrate dev && npm run db:worker",
"db:reset": "dotenv -e ../.env npx -- prisma migrate reset",
"db:deploy": "dotenv -e ../.env npx -- prisma migrate deploy",
"db:seed": "dotenv -e ../.env -- npx prisma db seed",
"db:seed:examples": "dotenv -e ../.env -- npx prisma db seed -- --environment examples",
"db:seed:load": "dotenv -e ../.env -- npx prisma db seed -- --environment load",
"release": "dotenv -e ../.env -- release-it",
"models:migrate": "dotenv -e ../.env -- tsx scripts/model-match.ts",
"db:worker": "cp -r prisma/generated ../worker"
},
"prisma": {
"seed": "ts-node -r tsconfig-paths/register -r dotenv/config --compiler-options {\"module\":\"CommonJS\"} prisma/seed.ts"
},
"dependencies": {
"@anthropic-ai/tokenizer": "^0.0.4",
"@aws-sdk/client-s3": "^3.507.0",
"@aws-sdk/lib-storage": "^3.515.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.10.2",
"@radix-ui/react-accordion": "^1.1.2",
"@radix-ui/react-alert-dialog": "^1.0.5",
"@radix-ui/react-avatar": "^1.0.4",
"@radix-ui/react-checkbox": "^1.0.4",
"@radix-ui/react-collapsible": "^1.0.3",
"@radix-ui/react-dialog": "^1.0.5",
"@radix-ui/react-dropdown-menu": "^2.0.6",
"@radix-ui/react-hover-card": "^1.0.7",
"@radix-ui/react-icons": "^1.3.0",
"@radix-ui/react-label": "^2.0.2",
"@radix-ui/react-popover": "^1.0.7",
"@radix-ui/react-scroll-area": "^1.0.5",
"@radix-ui/react-select": "^2.0.0",
"@radix-ui/react-separator": "^1.0.3",
"@radix-ui/react-slider": "^1.1.2",
"@radix-ui/react-slot": "^1.0.2",
"@radix-ui/react-switch": "^1.0.3",
"@radix-ui/react-tabs": "^1.0.4",
"@radix-ui/react-toggle": "^1.0.3",
"@radix-ui/react-tooltip": "^1.0.7",
"@react-email/components": "^0.0.14",
"@react-email/render": "^0.0.12",
"@sentry/nextjs": "^7.102.1",
"@sentry/profiling-node": "^7.102.1",
"@sentry/types": "^7.88.0",
"@t3-oss/env-nextjs": "^0.8.0",
"@tailwindcss/forms": "^0.5.7",
"@tanstack/react-query": "^4.36.1",
"@tanstack/react-table": "^8.11.8",
"@tremor/react": "^3.11.1",
"@trpc/client": "^10.45.0",
"@trpc/next": "^10.45.0",
"@trpc/react-query": "^10.45.0",
"@trpc/server": "^10.45.0",
"bcryptjs": "^2.4.3",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.0",
"cmdk": "^0.2.1",
"core-js": "^3.36.0",
"cors": "^2.8.5",
"date-fns": "^3.3.1",
"decimal.js": "^10.4.3",
"exponential-backoff": "^3.1.1",
"js-tiktoken": "^1.0.10",
"kysely": "^0.27.2",
"lodash": "^4.17.21",
"lucide-react": "^0.330.0",
"next": "^14.1.0",
"next-auth": "^4.24.6",
"next-query-params": "^5.0.0",
"nodemailer": "^6.9.9",
"posthog-js": "^1.105.9",
"posthog-node": "^3.6.3",
"prisma-kysely": "^1.8.0",
"react": "18.2.0",
"react-day-picker": "^8.10.0",
"react-dom": "18.2.0",
"react-hook-form": "^7.50.1",
"react-icons": "^5.0.1",
"react-responsive": "^9.0.2",
"react18-json-view": "^0.2.8-canary.1",
"sonner": "^1.4.0",
"superjson": "2.2.1",
"tailwind-merge": "^2.2.1",
"tailwindcss-animate": "^1.0.7",
"use-query-params": "^2.2.1",
"uuid": "^9.0.1",
"zod": "^3.22.4"
},
"devDependencies": {
"@jedmao/location": "^3.0.0",
"@mermaid-js/mermaid-cli": "^10.7.0",
"@playwright/test": "^1.41.2",
"@release-it/bumper": "^6.0.1",
"@testing-library/jest-dom": "^6.4.2",
"@testing-library/react": "^14.2.1",
"@types/bcryptjs": "^2.4.6",
"@types/cors": "^2.8.17",
"@types/eslint": "^8.56.2",
"@types/jest": "^29.5.12",
"@types/lodash": "^4.14.202",
"@types/node": "20.10.5",
"@types/nodemailer": "^6.4.14",
"@types/react": "^18.2.55",
"@types/react-dom": "^18.2.19",
"@types/uuid": "^9.0.8",
"@typescript-eslint/eslint-plugin": "^6.21.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",
"node-mocks-http": "^1.14.1",
"postcss": "^8.4.35",
"prettier": "^3.2.5",
"prettier-plugin-tailwindcss": "^0.5.11",
"prisma": "^5.10.2",
"prisma-erd-generator": "^1.11.2",
"release-it": "^17.1.1",
"tailwindcss": "^3.4.1",
"ts-node": "^10.9.2",
"tsconfig-paths": "^4.2.0",
"tsx": "^4.7.1",
"typescript": "^5.3.3"
},
"ct3aMetadata": {
"initVersion": "7.13.0"
},
"optionalDependencies": {
"crisp-sdk-web": "^1.0.21"
},
"release-it": {
"git": {
"commitMessage": "chore: release v${version}",
"tagName": "v${version}"
},
"github": {
"release": true,
"web": true,
"autoGenerate": true,
"releaseName": "v${version}",
"comments": {
"submit": true,
"issue": ":rocket: _This issue has been resolved in v${version}. See [${releaseName}](${releaseUrl}) for release notes._",
"pr": ":rocket: _This pull request is included in v${version}. See [${releaseName}](${releaseUrl}) for release notes._"
}
},
"plugins": {
"@release-it/bumper": {
"out": {
"file": "./src/constants/VERSION.ts",
"type": "application/typescript"
}
}
}
}
}

Before

Width:  |  Height:  |  Size: 194 KiB

After

Width:  |  Height:  |  Size: 194 KiB

@@ -225,7 +225,7 @@ export type ObservationView = {
calculated_input_cost: string | null;
calculated_output_cost: string | null;
calculated_total_cost: string | null;
latency: string | null;
latency: number | null;
};
export type Pricing = {
id: string;

Some files were not shown because too many files have changed in this diff Show More