Compare commits

...
314 Commits
Author SHA1 Message Date
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
Max Deichmann c02bb556ca chore: release v2.7.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-20 20:05:45 +01:00
Richard KrümmelandGitHub 1b792d844f fix(ui): fix prompt config display logic (#1211) 2024-02-20 13:57:45 +01:00
Max DeichmannandGitHub 52a42812b4 refactor: add kysely (#1210) 2024-02-20 11:24:22 +00:00
3b84af8cbf feat: add prompt config (#1147)
Co-authored-by: Max Deichmann <m.deichmann@tum.de>
2024-02-20 10:31:44 +00:00
Marc KlingenandGitHub 1521445939 fix(ui): uriencode filter state to support special characters (#1209) 2024-02-20 00:56:18 +00:00
Marc KlingenandGitHub a1e961de09 feat(api): add htmlPath and totalCost to GET traces/[id] (#1207) 2024-02-20 00:34:59 +00:00
Marc Klingen c360cf10d4 chore: release v2.6.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-19 23:35:23 +01:00
Marc KlingenandGitHub 3e2f3f3d28 feat(api): add GET metrics/daily endpoint to fetch aggregate statistics (#1204) 2024-02-19 23:29:51 +01:00
Richard KrümmelandGitHub 11e5da2cd8 feat(ui): show full id in session table (#1165) 2024-02-19 22:09:08 +00:00
Max DeichmannandGitHub 8205595f2c fix: fix scores table (#1205) 2024-02-19 20:49:15 +00:00
101277cab8 feat: add traces filter to dashboard (#1202)
Co-authored-by: RichardKruemmel <richard.kruemmel@code.berlin>
2024-02-19 20:36:12 +00:00
Marc Klingen 954e31ca4a fix(api): type of totalCost on trace 2024-02-19 17:51:49 +01:00
Marc KlingenandGitHub 43c3258135 feat(api): add htmlPath, latency, totalCost to GET /traces (#1201) 2024-02-19 15:39:02 +00:00
Marc KlingenandGitHub eb8ae94a5d feat(dashboard): add 75th percentile to latency graph (#1195) 2024-02-17 12:07:39 +00:00
George GebbettandGitHub 33abe53acc feat(ui): preview of OpenAI function calls (#981) 2024-02-16 15:47:51 +00:00
5e8ec0bd13 feat(api): add DELETE /api/public/score/[scoreId] (#1167)
---------

Co-authored-by: Marc Klingen <git@marcklingen.com>
2024-02-16 15:06:02 +00:00
177f370914 feat: display total cost of a session (#1172)
Co-authored-by: gitstart-langfuse <gitstart-langfuse@users.noreply.github.com>
Co-authored-by: Max Deichmann <m.deichmann@tum.de>
2024-02-16 15:12:38 +01:00
5538242649 feat: show total model cost per user (#1173)
Co-authored-by: gitstart-langfuse <gitstart-langfuse@users.noreply.github.com>
Co-authored-by: Max Deichmann <m.deichmann@tum.de>
2024-02-16 15:02:18 +01:00
8c8e58e2b8 fix: Correct sorting on all tables (#1168)
Co-authored-by: gitstart-langfuse <gitstart-langfuse@users.noreply.github.com>
Co-authored-by: Max Deichmann <m.deichmann@tum.de>
2024-02-16 13:00:11 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
a2c367c1b6 chore(deps): bump core-js from 3.35.1 to 3.36.0 (#1177)
Bumps [core-js](https://github.com/zloirock/core-js/tree/HEAD/packages/core-js) from 3.35.1 to 3.36.0.
- [Release notes](https://github.com/zloirock/core-js/releases)
- [Changelog](https://github.com/zloirock/core-js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/zloirock/core-js/commits/v3.36.0/packages/core-js)

---
updated-dependencies:
- dependency-name: core-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-16 03:03:39 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
da0ac73603 chore(deps): bump the patches group with 4 updates (#1176)
Bumps the patches group with 4 updates: [@sentry/nextjs](https://github.com/getsentry/sentry-javascript), [@sentry/profiling-node](https://github.com/getsentry/sentry-javascript), [@sentry/types](https://github.com/getsentry/sentry-javascript) and [posthog-node](https://github.com/PostHog/posthog-js-lite/tree/HEAD/posthog-node).


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

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

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

Updates `posthog-node` from 3.6.2 to 3.6.3
- [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.3/posthog-node)

---
updated-dependencies:
- dependency-name: "@sentry/nextjs"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patches
- dependency-name: "@sentry/profiling-node"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patches
- dependency-name: "@sentry/types"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patches
- dependency-name: posthog-node
  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-16 02:59:15 +00:00
Marc Klingen e60e74478c chore: release v2.5.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-16 03:13:32 +01:00
Marc KlingenandGitHub 329f83e844 feat(api): optionally set timestamp when creating a trace (#1181)
Fixes #1157
2024-02-16 01:53:00 +00:00
Marc KlingenandGitHub 28c035da76 refactor: rbac access checks (#1180) 2024-02-16 01:35:22 +00:00
Max Deichmann 4dfeceb9d6 chore: release v2.5.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-15 23:14:05 +01:00
Max DeichmannandGitHub df802184a6 fix: fix order of matched models (#1175) 2024-02-15 22:11:50 +00:00
Marc KlingenandGitHub 407d169095 feat(api): add latency to generations endpoints (#1169) 2024-02-15 23:01:24 +01:00
Max DeichmannandGitHub e1958e73d4 fix: fix gpt-4-turbo-preview prices (#1174) 2024-02-15 21:20:47 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2a08c3395c chore(deps): bump the sentry group with 3 updates (#1151)
Bumps the sentry group 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.100.1 to 7.101.0
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/7.100.1...7.101.0)

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

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

---
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-15 02:19:16 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
5c405f4ed8 chore(deps): bump the patches group with 3 updates (#1162)
Bumps the patches group with 3 updates: [next-auth](https://github.com/nextauthjs/next-auth), [posthog-js](https://github.com/PostHog/posthog-js) and [release-it](https://github.com/release-it/release-it).


Updates `next-auth` from 4.24.5 to 4.24.6
- [Release notes](https://github.com/nextauthjs/next-auth/releases)
- [Commits](https://github.com/nextauthjs/next-auth/compare/next-auth@4.24.5...next-auth@4.24.6)

Updates `posthog-js` from 1.105.7 to 1.105.9
- [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/1.105.7...v1.105.9)

Updates `release-it` from 17.0.3 to 17.0.5
- [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.3...17.0.5)

---
updated-dependencies:
- dependency-name: next-auth
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patches
- dependency-name: posthog-js
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patches
- dependency-name: release-it
  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-15 02:14:33 +00:00
Marc Klingen 25cc29f353 fix(ui): color of checkboxes 2024-02-15 01:36:02 +01:00
Marc Klingen b5e1b9916f chore: release v2.4.3
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-15 01:15:58 +01:00
Marc KlingenandGitHub 8075996a1c fix(ui): overflow and responsive ui in trace view (#1164) 2024-02-15 00:13:48 +00:00
Marc KlingenandGitHub 80cc85d756 perf(prompts): add db indicies on project_id and id (#1163) 2024-02-14 23:30:41 +00:00
Marc KlingenandGitHub 45c611bc6d fix(prompts): allow underscores in variables when editing a prompt via UI (#1161) 2024-02-14 23:25:09 +01:00
Richard KrümmelandGitHub 1478aa9c2b fix: dashboard drop down selector on mobile view (#1153) 2024-02-14 14:53:13 +01:00
Marc KlingenandGitHub 4944408b62 fix(cloud): show plan limit only on hobby plan (#1152) 2024-02-14 01:09:18 +00:00
Marc Klingen f6e81f818b fix(cloud): hobby plan usage limit 2024-02-14 01:06:07 +01:00
Marc KlingenandGitHub b2d5839dcd chore(cloud): update stripe billing link (#1149) 2024-02-13 22:03:54 +00:00
Marc Klingen 2608878d20 chore: release v2.4.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-13 15:53:15 +01:00
Marc Klingen 62a2857619 docs: add DB_EXPORT_PAGE_SIZE to .env.prod.example 2024-02-13 15:48:49 +01:00
0c1942c2b3 fix(docker): remove the need for runtime variables at build time (#1067)
---------

Co-authored-by: Marc Klingen <git@marcklingen.com>
2024-02-13 15:40:16 +01:00
b95c93cdb1 fix: memory optimizes generation.export trpc to allow for larger exports (#1124)
* fix: memory optimizes generation.export trpc

* test: disable S3 uploads in export test

* refactor: modularize generations.export

* feat: adds streaming to S3 bucket

* feat: adds DB_EXPORT_PAGE_SIZE environment variable

* refactor: clean up generationsRouter

---------

Co-authored-by: Max Deichmann <m.deichmann@tum.de>
2024-02-13 12:55:12 +00:00
Marc Klingen 3691099c74 chore: release v2.4.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-13 13:26:51 +01:00
Marc KlingenandGitHub 3f1ae71eec fix: feedback api route (#1146)
Fixes #1144
2024-02-13 13:14:27 +01:00
Max DeichmannandGitHub 668cf3f6c2 Feat: update openai pricing (#1145) 2024-02-13 11:36:22 +00:00
Marc KlingenandGitHub 6221be155d feat(security): add audit logging (#1142) 2024-02-13 11:35:54 +01:00
Marc KlingenandGitHub 3e13d191db chore: drop middleware previously used for IP blocklisting (#1143) 2024-02-12 22:53:07 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
61297826f4 chore(deps): bump lucide-react from 0.323.0 to 0.330.0 (#1140)
Bumps [lucide-react](https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react) from 0.323.0 to 0.330.0.
- [Release notes](https://github.com/lucide-icons/lucide/releases)
- [Commits](https://github.com/lucide-icons/lucide/commits/0.330.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-12 23:47:36 +01:00
Max DeichmannandGitHub 3268ef6488 style: adjust contributing template (#1136)
remove
2024-02-12 20:54:20 +01:00
Marc Klingen 4aba13ec35 chore: release v2.4.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-12 17:52:28 +01:00
Marc Klingen 0f5d5cd9a0 fix(ui): invalidation of traces after delete 2024-02-12 17:46:58 +01:00
Marc KlingenandGitHub 78df145e20 fix(ui): invalidation of traces when deleting a single trace (#1134) 2024-02-12 12:00:57 +00:00
Max DeichmannandGitHub b35618f1c9 refactor: add betterstack env variable to env.prod.example (#1132) 2024-02-12 10:17:51 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
a139ada85e chore(deps): bump the sentry group with 3 updates (#1110)
Bumps the sentry group 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.99.0 to 7.100.1
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/7.100.1/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/7.99.0...7.100.1)

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

Updates `@sentry/types` from 7.99.0 to 7.100.1
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/7.100.1/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/7.99.0...7.100.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-major
  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-12 00:07:57 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
cdfb0c6b7c chore(deps): bump posthog-js from 1.104.4 to 1.105.7 (#1131)
Bumps [posthog-js](https://github.com/PostHog/posthog-js) from 1.104.4 to 1.105.7.
- [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.104.4...1.105.7)

---
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-12 01:02:10 +01:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
c0bbf39b29 chore(deps-dev): bump the patches group with 3 updates (#1130)
Bumps the patches group with 3 updates: [@types/react-dom](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react-dom), [postcss](https://github.com/postcss/postcss) and [tsx](https://github.com/privatenumber/tsx).


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

Updates `postcss` from 8.4.34 to 8.4.35
- [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.34...8.4.35)

Updates `tsx` from 4.7.0 to 4.7.1
- [Release notes](https://github.com/privatenumber/tsx/releases)
- [Changelog](https://github.com/privatenumber/tsx/blob/develop/release.config.cjs)
- [Commits](https://github.com/privatenumber/tsx/compare/v4.7.0...v4.7.1)

---
updated-dependencies:
- dependency-name: "@types/react-dom"
  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: tsx
  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-11 23:44:28 +00:00
Marc Klingen a6900ad3c4 fix(ui): use lightner colors in observation tree 2024-02-12 00:31:00 +01:00
21940a0464 feat(ui): improve trace view: collapse/expand observation tree + color coding of observation types (#916)
---------

Co-authored-by: Marc Klingen <git@marcklingen.com>
2024-02-11 23:47:46 +01:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
fe642f8e9e chore(deps-dev): bump @typescript-eslint/eslint-plugin from 6.20.0 to 6.21.0 (#1112)
chore(deps-dev): bump @typescript-eslint/eslint-plugin

Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) 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/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v6.21.0/packages/eslint-plugin)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  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-11 22:05:53 +00:00
c803b0d9c2 feat(ui): delete prompts and prompt versions + deduplication of prompt variables (#1116)
* fix and feat: update Var renaming and add functionality to delete prompt and versions

* pass ci by removing unused components

* ux improvements

---------

Co-authored-by: Marc Klingen <git@marcklingen.com>
2024-02-11 22:00:31 +00:00
Marc KlingenandGitHub e7086cf044 fix(ci): temporarily fix modelmatch test by waiting 5 sec (#1129)
* fix(ci): temporarily fix modelmatch test by waiting 5 sec

* fix
2024-02-11 21:56:19 +00:00
Marc KlingenandGitHub 9d49bbe987 chore(ui): responsive layout (#1126) 2024-02-10 03:29:38 +00:00
Marc Klingen f2c792d3dc chore: release v2.3.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-09 21:38:20 +01:00
Marc Klingen 0527fcf097 fix(ui): add space 2024-02-09 21:30:06 +01:00
Max DeichmannandGitHub 85737221d9 feat: send sdk logs to betterstack (#1125) 2024-02-09 20:01:46 +00:00
ffe95cf427 feat(ui): add request dashboard button (#1122)
Co-authored-by: Max Deichmann <m.deichmann@tum.de>
2024-02-09 19:25:08 +00:00
adec1476ea feat(ui): add quickstart examples to api key creation popup (#1119)
---------

Co-authored-by: Marc Klingen <git@marcklingen.com>
2024-02-09 19:10:21 +00:00
c5d7772fe6 chore(ui): convert model pricing in UI to per 1000 units (#1123)
Co-authored-by: Max Deichmann <m.deichmann@tum.de>
2024-02-09 19:05:04 +00:00
Max DeichmannandGitHub a88a6b8026 fix: upgrade API keys (#1120) 2024-02-09 16:44:48 +00:00
Marc Klingen 5d77e09eed docs: update readme and contributing 2024-02-09 15:38:22 +01:00
Hassieb PakzadandGitHub 85e5ea4661 fix: allow bearer auth for score ingestion via /api/public/ingestion (#1117)
* fix: allow bearer auth for score ingestion

* tests: add test for opening ingestion endpoint for scoring

* test: adds db check for bearer auth tests in ingestion
2024-02-09 13:51:22 +01:00
366df5a5c9 Fix decimals in scores filter on traces + generations table (#1012)
Co-authored-by: gitstart-langfuse <gitstart-langfuse@users.noreply.github.com>
Co-authored-by: GitStart-LangFuse <151670644+gitstart-langfuse@users.noreply.github.com>
Co-authored-by: Max Deichmann <m.deichmann@tum.de>
2024-02-09 08:44:12 +01:00
4441383dfd docs: update readme (#1107)
docs: update and significantly shorten readme
---------

Co-authored-by: Clemo <121163007+clemra@users.noreply.github.com>
2024-02-08 22:18:02 +00:00
Richard KrümmelandGitHub 7f7696e9ff feat(ui): add in-product notifications (#1057) 2024-02-08 19:41:30 +00:00
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
Marc Klingen cd537fb571 chore: release v2.1.2
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 42s
CI/CD / test-docker-build (push) Successful in 2m59s
CI/CD / e2e-tests (push) Failing after 45s
release.yml / release (push) Failing after 3s
CI/CD / lint (push) Failing after 22m27s
CI/CD / all-ci-passed (push) Waiting to run
2024-02-02 23:22:12 +01:00
Marc KlingenandGitHub 3cbd252980 chore(cloud): add environment labeling (#1058) 2024-02-02 23:02:19 +01:00
Max DeichmannandGitHub 0a99988e6e perf: do not load observation i/o from db on traces.byId (#1053) 2024-02-02 16:01:19 +00:00
Marc KlingenandGitHub a19d20d973 fix: remove Expires from S3 PutObject (#1047)
Fixes #1046
2024-02-02 03:56:47 +01:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
b86eab9e04 chore(deps-dev): bump the patches group with 1 update (#1037)
Bumps the patches group with 1 update: [@playwright/test](https://github.com/microsoft/playwright).


Updates `@playwright/test` from 1.41.1 to 1.41.2
- [Release notes](https://github.com/microsoft/playwright/releases)
- [Commits](https://github.com/microsoft/playwright/compare/v1.41.1...v1.41.2)

---
updated-dependencies:
- dependency-name: "@playwright/test"
  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-02 00:57:37 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
b36530ff96 chore(deps): bump lucide-react from 0.316.0 to 0.321.0 (#1039)
Bumps [lucide-react](https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react) from 0.316.0 to 0.321.0.
- [Release notes](https://github.com/lucide-icons/lucide/releases)
- [Commits](https://github.com/lucide-icons/lucide/commits/0.321.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-02 00:50:03 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
1019298060 chore(deps-dev): bump @testing-library/react from 14.1.2 to 14.2.1 (#1040)
Bumps [@testing-library/react](https://github.com/testing-library/react-testing-library) from 14.1.2 to 14.2.1.
- [Release notes](https://github.com/testing-library/react-testing-library/releases)
- [Changelog](https://github.com/testing-library/react-testing-library/blob/main/CHANGELOG.md)
- [Commits](https://github.com/testing-library/react-testing-library/compare/v14.1.2...v14.2.1)

---
updated-dependencies:
- dependency-name: "@testing-library/react"
  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-02 00:45:30 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
99a2ad30ce chore(deps-dev): bump @typescript-eslint/parser from 6.19.1 to 6.20.0 (#1038)
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 6.19.1 to 6.20.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.20.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-02 00:40:21 +00:00
Marc Klingen 9783a22abf chore: release v2.1.1
CI/CD / push-docker-image (push) Blocked by required conditions
CI/CD / test-docker-build (push) Successful in 2m42s
CI/CD / tests (18) (push) Failing after 1m13s
CI/CD / tests (20) (push) Failing after 42s
CI/CD / e2e-tests (push) Failing after 44s
CI/CD / lint (push) Successful in 4m9s
CI/CD / all-ci-passed (push) Waiting to run
release.yml / release (push) Failing after 17s
2024-02-02 00:48:34 +01:00
Marc KlingenandGitHub 68f63b3b90 fix(ui): generation exports from UI (#1042) 2024-02-02 00:18:58 +01:00
Marc Klingen 1189d13c14 chore: release v2.1.0
CI/CD / push-docker-image (push) Blocked by required conditions
CI/CD / tests (20) (push) Failing after 47s
CI/CD / e2e-tests (push) Failing after 44s
CI/CD / lint (push) Successful in 4m1s
CI/CD / test-docker-build (push) Successful in 3m43s
release.yml / release (push) Failing after 3s
CI/CD / tests (18) (push) Failing after 11m20s
CI/CD / all-ci-passed (push) Waiting to run
2024-02-01 21:08:59 +01:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
243a784480 chore(deps): bump the patches group with 4 updates (#1035)
Bumps the patches group with 4 updates: cmdk, [@testing-library/jest-dom](https://github.com/testing-library/jest-dom), [@types/jest](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/jest) and [@types/react](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react).


Updates `cmdk` from 0.2.0 to 0.2.1

Updates `@testing-library/jest-dom` from 6.4.0 to 6.4.1
- [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.0...v6.4.1)

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

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

---
updated-dependencies:
- dependency-name: cmdk
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patches
- dependency-name: "@testing-library/jest-dom"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: patches
- dependency-name: "@types/jest"
  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
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-01 21:08:19 +01:00
c89b8c3bab fix(ui): update regex matching description (#1031)
---------

Co-authored-by: Marc Klingen <git@marcklingen.com>
2024-02-01 20:54:57 +01:00
b5172219af security: upgrade nodemailer from 6.9.8 to 6.9.9 (#1027)
* fix: package.json to reduce vulnerabilities

The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/SNYK-JS-NODEMAILER-6219989

* update

---------

Co-authored-by: snyk-bot <snyk-bot@snyk.io>
2024-02-01 20:53:40 +01:00
Marc Klingen db90f85041 fix(ui): disabled state of AddModel button 2024-02-01 17:41:19 +01:00
Marc KlingenandGitHub db9f90aa91 fix(models): allow price = 0 (#1030) 2024-02-01 15:56:51 +00:00
Marc KlingenandGitHub 41b19582cc feat(models): allow to set input/output/total price without restrictions (#1029) 2024-02-01 16:50:25 +01:00
766102797b feat(models): allow custom regex for user-defined models (#1022)
---------

Co-authored-by: Marc Klingen <git@marcklingen.com>
2024-02-01 16:42:21 +01:00
Max Deichmann 773cb1312b chore: release v2.0.1
CI/CD / push-docker-image (push) Blocked by required conditions
CI/CD / tests (18) (push) Failing after 1m0s
CI/CD / test-docker-build (push) Successful in 3m27s
CI/CD / e2e-tests (push) Failing after 49s
CI/CD / tests (20) (push) Failing after 1m39s
CI/CD / lint (push) Successful in 4m44s
CI/CD / all-ci-passed (push) Waiting to run
release.yml / release (push) Failing after 3s
2024-02-01 16:31:54 +01:00
Max DeichmannandGitHub bb593020d0 fix: gh action (#1028) 2024-02-01 16:27:06 +01:00
Max DeichmannandGitHub 33ffe62add fix: display total cost correctly (#1026) 2024-02-01 14:56:49 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
6e1aabb2de chore(deps-dev): bump @testing-library/jest-dom from 6.2.1 to 6.4.0 (#988)
Bumps [@testing-library/jest-dom](https://github.com/testing-library/jest-dom) from 6.2.1 to 6.4.0.
- [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.2.1...v6.4.0)

---
updated-dependencies:
- dependency-name: "@testing-library/jest-dom"
  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-01-31 22:14:20 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
ab3bdebc57 chore(deps): bump the sentry group with 1 update (#1000)
Bumps the sentry group with 1 update: [@sentry/nextjs](https://github.com/getsentry/sentry-javascript).


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

---
updated-dependencies:
- dependency-name: "@sentry/nextjs"
  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-01-31 22:09:55 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
20d00e5ef2 chore(deps-dev): bump @mermaid-js/mermaid-cli from 10.6.1 to 10.7.0 (#1003)
Bumps [@mermaid-js/mermaid-cli](https://github.com/mermaid-js/mermaid-cli) from 10.6.1 to 10.7.0.
- [Release notes](https://github.com/mermaid-js/mermaid-cli/releases)
- [Commits](https://github.com/mermaid-js/mermaid-cli/compare/10.6.1...10.7.0)

---
updated-dependencies:
- dependency-name: "@mermaid-js/mermaid-cli"
  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-01-31 22:04:28 +00:00
Marc Klingen e689c1cacb chore: move github discussions to org level 2024-01-31 22:59:35 +01:00
Richard KrümmelandGitHub 37c0737624 feat(db): add openai fine tuned and vertex ai models (#995) 2024-01-31 14:19:17 +01:00
23bc448088 fix(ui): fix create new model label (#1005)
Co-authored-by: Max Deichmann <m.deichmann@tum.de>
2024-01-31 11:46:15 +01:00
Max Deichmann f1bdea98be chore: release v2.0.0
CI/CD / push-docker-image (push) Blocked by required conditions
CI/CD / tests (20) (push) Failing after 45s
CI/CD / tests (18) (push) Failing after 1m17s
CI/CD / e2e-tests (push) Failing after 45s
CI/CD / test-docker-build (push) Successful in 3m16s
CI/CD / lint (push) Successful in 4m1s
CI/CD / all-ci-passed (push) Waiting to run
release.yml / release (push) Failing after 4s
2024-01-30 19:56:07 +01:00
Max DeichmannandGitHub 9c00d1905f perf: reduce batch size (#997) 2024-01-30 17:47:31 +00:00
Max DeichmannandGitHub a31d737538 perf: improve migration script (#996) 2024-01-30 17:00:57 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
7535872222 chore(deps-dev): bump @typescript-eslint/eslint-plugin from 6.19.1 to 6.20.0 (#985)
chore(deps-dev): bump @typescript-eslint/eslint-plugin

Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 6.19.1 to 6.20.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v6.20.0/packages/eslint-plugin)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  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-01-30 15:47:44 +00:00
7e7bf99fac refactor: improve usage/cost (#992)
---------

Co-authored-by: Max Deichmann <m.deichmann@tum.de>
2024-01-30 15:43:08 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
ac5a7a3171 chore(deps): bump the patches group with 1 update (#983)
Bumps the patches group with 1 update: [js-tiktoken](https://github.com/dqbd/tiktoken).


Updates `js-tiktoken` from 1.0.8 to 1.0.10
- [Release notes](https://github.com/dqbd/tiktoken/releases)
- [Changelog](https://github.com/dqbd/tiktoken/blob/main/CHANGELOG.md)
- [Commits](https://github.com/dqbd/tiktoken/compare/js-tiktoken@1.0.8...js-tiktoken@1.0.10)

---
updated-dependencies:
- dependency-name: js-tiktoken
  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-01-30 01:03:47 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
eda5da635d chore(deps): bump clsx from 2.0.0 to 2.1.0 (#986)
Bumps [clsx](https://github.com/lukeed/clsx) from 2.0.0 to 2.1.0.
- [Release notes](https://github.com/lukeed/clsx/releases)
- [Commits](https://github.com/lukeed/clsx/compare/v2.0.0...v2.1.0)

---
updated-dependencies:
- dependency-name: clsx
  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-01-30 01:56:29 +01:00
Max DeichmannandGitHub dc0cef5dbb feat: add cost to observations API (#947) 2024-01-29 19:09:16 +01:00
Marc KlingenandGitHub 24607c10ee chore(deps): bump dependencies (#979) 2024-01-29 15:23:15 +00:00
Marc KlingenandGitHub 8ddcfa8136 refactor: typing of AutoCompleteOption (#978) 2024-01-29 15:15:47 +00:00
Max DeichmannandGitHub 1f54043778 refactor: correct model migration command (#977) 2024-01-29 15:04:31 +00:00
Richard KrümmelandGitHub 97bec94093 feat(db): improve seeding script for prompts (#965) 2024-01-29 14:16:38 +01:00
93df11e043 feat: Add filtering by scores to the generations table (#880)
Co-authored-by: gitstart_bot <gitstart_bot@users.noreply.github.com>
Co-authored-by: gitstart-langfuse <gitstart-langfuse@users.noreply.github.com>
Co-authored-by: Max Deichmann <m.deichmann@tum.de>
2024-01-29 11:44:26 +01:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>Marc Klingen
327b66c241 chore(deps): bump the patches group with 13 updates (#970)
Bumps the patches group with 13 updates:

| Package | From | To |
| --- | --- | --- |
| [@headlessui/react](https://github.com/tailwindlabs/headlessui/tree/HEAD/packages/@headlessui-react) | `1.7.17` | `1.7.18` |
| [@react-email/components](https://github.com/resend/react-email/tree/HEAD/packages/components) | `0.0.12` | `0.0.14` |
| [@react-email/render](https://github.com/resend/react-email/tree/HEAD/packages/render) | `0.0.10` | `0.0.12` |
| [@tanstack/react-table](https://github.com/TanStack/table/tree/HEAD/packages/react-table) | `8.11.3` | `8.11.7` |
| [core-js](https://github.com/zloirock/core-js/tree/HEAD/packages/core-js) | `3.35.0` | `3.35.1` |
| [react-hook-form](https://github.com/react-hook-form/react-hook-form) | `7.49.2` | `7.49.3` |
| [tailwind-merge](https://github.com/dcastil/tailwind-merge) | `2.2.0` | `2.2.1` |
| [@types/eslint](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/eslint) | `8.56.1` | `8.56.2` |
| [@types/react](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react) | `18.2.46` | `18.2.48` |
| [@types/uuid](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/uuid) | `9.0.7` | `9.0.8` |
| [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) | `6.19.0` | `6.19.1` |
| [autoprefixer](https://github.com/postcss/autoprefixer) | `10.4.16` | `10.4.17` |
| [release-it](https://github.com/release-it/release-it) | `17.0.1` | `17.0.3` |


Updates `@headlessui/react` from 1.7.17 to 1.7.18
- [Release notes](https://github.com/tailwindlabs/headlessui/releases)
- [Changelog](https://github.com/tailwindlabs/headlessui/blob/main/packages/@headlessui-react/CHANGELOG.md)
- [Commits](https://github.com/tailwindlabs/headlessui/commits/@headlessui/react@v1.7.18/packages/@headlessui-react)

Updates `@react-email/components` from 0.0.12 to 0.0.14
- [Release notes](https://github.com/resend/react-email/releases)
- [Commits](https://github.com/resend/react-email/commits/v0.0.14/packages/components)

Updates `@react-email/render` from 0.0.10 to 0.0.12
- [Release notes](https://github.com/resend/react-email/releases)
- [Commits](https://github.com/resend/react-email/commits/v0.0.12/packages/render)

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

Updates `core-js` from 3.35.0 to 3.35.1
- [Release notes](https://github.com/zloirock/core-js/releases)
- [Changelog](https://github.com/zloirock/core-js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/zloirock/core-js/commits/v3.35.1/packages/core-js)

Updates `react-hook-form` from 7.49.2 to 7.49.3
- [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.2...v7.49.3)

Updates `tailwind-merge` from 2.2.0 to 2.2.1
- [Release notes](https://github.com/dcastil/tailwind-merge/releases)
- [Commits](https://github.com/dcastil/tailwind-merge/compare/v2.2.0...v2.2.1)

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

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

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

Updates `@typescript-eslint/eslint-plugin` from 6.19.0 to 6.19.1
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v6.19.1/packages/eslint-plugin)

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

Updates `release-it` from 17.0.1 to 17.0.3
- [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.1...17.0.3)

---
updated-dependencies:
- dependency-name: "@headlessui/react"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patches
- dependency-name: "@react-email/components"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patches
- dependency-name: "@react-email/render"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patches
- dependency-name: "@tanstack/react-table"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patches
- dependency-name: core-js
  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: tailwind-merge
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patches
- dependency-name: "@types/eslint"
  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: "@types/uuid"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: patches
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: patches
- dependency-name: autoprefixer
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: patches
- dependency-name: release-it
  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>
Co-authored-by: Marc Klingen <git@marcklingen.com>
2024-01-27 19:08:09 +01:00
Marc KlingenandGitHub f3fd52fdbb feat(ui): custom model prices and tokenization (#954) 2024-01-27 18:52:31 +01:00
Marc KlingenandGitHub f3727c6209 revert(api): increase of max body size (#975) 2024-01-27 18:44:18 +01:00
Marc KlingenandGitHub 8a3281db03 chore: fix typo (#974) 2024-01-27 17:39:41 +00:00
Max Deichmann 19a21dca5a Merge branch 'main' of https://github.com/langfuse/langfuse 2024-01-26 23:45:06 +01:00
Max Deichmann 09dcad7427 perf: increase body size 2024-01-26 23:45:02 +01:00
Max DeichmannandGitHub 172cbed9b5 feat: add new openai model prices (#967) 2024-01-26 17:37:19 +00:00
Richard KrümmelandGitHub f7e20a9ff6 fix: error log for api prompts (#966) 2024-01-26 16:50:50 +01:00
Max DeichmannandGitHub 4b213151d1 fix: retrieve api prompts (#963) 2024-01-26 15:20:46 +00:00
Max DeichmannandGitHub dd99efe692 refactor: formatting (#962) 2024-01-26 13:41:40 +00:00
Richard KrümmelandGitHub ff303750cc feat(ui): add improved prompt ui (#961) 2024-01-26 14:20:58 +01:00
Max DeichmannandGitHub ef6e1e0bf4 perf: use js-tiktoken (#957) 2024-01-25 20:42:46 +01:00
Max DeichmannandGitHub c0ed93132f fix: support emoji in tokenizer (#956) 2024-01-25 11:18:53 +00:00
Max DeichmannandGitHub 3503537539 refactor: db logging in dev mode (#952) 2024-01-24 18:35:23 +00:00
Max DeichmannandGitHub b9a3f33e97 fix: fix token configuration (#951) 2024-01-24 18:14:28 +00:00
Max DeichmannandGitHub c2f612d0b8 fix: fix toktoken tokenizer for unexpected input (#950) 2024-01-24 15:55:24 +00:00
Marc KlingenandGitHub 9f492ecec9 fix(sessions): composite ids (#946) 2024-01-24 15:27:31 +01:00
Max DeichmannandGitHub d87432cce3 fix: pull metrics table from observations only (#945) 2024-01-24 12:46:41 +00:00
Max DeichmannandGitHub cf34c91734 fix: model usage chart (#944) 2024-01-24 12:20:34 +00:00
Max DeichmannandGitHub 851b54fa47 perf: Improve migration (#943) 2024-01-24 12:56:13 +01:00
Richard KrümmelandGitHub c858a1800b fix(security): add validation for html in inputs (#927) 2024-01-24 11:43:33 +01:00
Max DeichmannandGitHub f2405f1561 feat: revamp pricing and cost (#901) 2024-01-24 10:53:48 +01:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
deee890647 chore(deps-dev): bump @testing-library/jest-dom from 6.1.5 to 6.2.1 (#936)
Bumps [@testing-library/jest-dom](https://github.com/testing-library/jest-dom) from 6.1.5 to 6.2.1.
- [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.1.5...v6.2.1)

---
updated-dependencies:
- dependency-name: "@testing-library/jest-dom"
  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-01-24 00:18:28 +00:00
Marc Klingen ebabf0e100 chore: release v1.34.1
CI/CD / push-docker-image (push) Blocked by required conditions
CI/CD / tests (18) (push) Failing after 50s
CI/CD / tests (20) (push) Failing after 55s
release.yml / release (push) Failing after 3s
CI/CD / e2e-tests (push) Failing after 45s
CI/CD / test-docker-build (push) Successful in 3m12s
CI/CD / lint (push) Successful in 4m0s
CI/CD / all-ci-passed (push) Waiting to run
2024-01-24 01:12:22 +01:00
Marc KlingenandGitHub e05d4693d2 fix(ui): encodeURIComponent for session and user ids (#940)
Before, special characters in those ids would break the UI as the ids are used as URI components
2024-01-24 01:11:37 +01:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
77d49adc00 chore(deps): bump react-icons from 4.12.0 to 5.0.1 (#935)
Bumps [react-icons](https://github.com/react-icons/react-icons) from 4.12.0 to 5.0.1.
- [Release notes](https://github.com/react-icons/react-icons/releases)
- [Commits](https://github.com/react-icons/react-icons/compare/v4.12.0...v5.0.1)

---
updated-dependencies:
- dependency-name: react-icons
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-23 23:55:10 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
7dc45f0074 chore(deps): bump lucide-react from 0.306.0 to 0.314.0 (#937)
Bumps [lucide-react](https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react) from 0.306.0 to 0.314.0.
- [Release notes](https://github.com/lucide-icons/lucide/releases)
- [Commits](https://github.com/lucide-icons/lucide/commits/0.314.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-01-24 00:49:42 +01:00
44d1da3c9c fix: fix playwright test timeouts (#868)
Co-authored-by: gitstart_bot <gitstart_bot@users.noreply.github.com>
Co-authored-by: gitstart-langfuse <gitstart-langfuse@users.noreply.github.com>
Co-authored-by: Max Deichmann <m.deichmann@tum.de>
2024-01-23 23:47:53 +01:00
jhlopenandGitHub 564ba4bd68 chore: mitigate type truncation in VS Code tooltip (#932) 2024-01-23 23:38:30 +01:00
Marc Klingen 63df788908 chore: release v1.34.0
CI/CD / push-docker-image (push) Blocked by required conditions
CI/CD / tests (18) (push) Failing after 47s
CI/CD / tests (20) (push) Failing after 44s
release.yml / release (push) Failing after 2s
CI/CD / e2e-tests (push) Failing after 41s
CI/CD / test-docker-build (push) Successful in 3m14s
CI/CD / lint (push) Successful in 5m59s
CI/CD / all-ci-passed (push) Waiting to run
2024-01-23 22:59:17 +01:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
fb463cbf98 chore(deps): bump the sentry group with 2 updates (#931)
Bumps the sentry group with 2 updates: [@sentry/nextjs](https://github.com/getsentry/sentry-javascript) and [@sentry/profiling-node](https://github.com/getsentry/profiling-node).


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

Updates `@sentry/profiling-node` from 1.3.2 to 1.3.5
- [Release notes](https://github.com/getsentry/profiling-node/releases)
- [Changelog](https://github.com/getsentry/profiling-node/blob/main/CHANGES)
- [Commits](https://github.com/getsentry/profiling-node/compare/v1.3.2...v1.3.5)

---
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-patch
  dependency-group: sentry
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-23 21:56:41 +00:00
Marc KlingenandGitHub cfd99efd48 feat(ui): add ordering to sessions table (#930) 2024-01-23 21:33:12 +00:00
Marc KlingenandGitHub 3b2c5f8bf3 feat(ui): add ordering to generations table (#929) 2024-01-23 21:23:47 +00:00
Marc KlingenandGitHub d08a276b67 perf: revert splitting of generations trpc call (#928) 2024-01-23 21:03:17 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
23bc2cd39c chore(deps): bump the next group with 2 updates (#924)
Bumps the next group with 2 updates: [next](https://github.com/vercel/next.js) and [eslint-config-next](https://github.com/vercel/next.js/tree/HEAD/packages/eslint-config-next).


Updates `next` from 14.0.4 to 14.1.0
- [Release notes](https://github.com/vercel/next.js/releases)
- [Changelog](https://github.com/vercel/next.js/blob/canary/release.js)
- [Commits](https://github.com/vercel/next.js/compare/v14.0.4...v14.1.0)

Updates `eslint-config-next` from 14.0.4 to 14.1.0
- [Release notes](https://github.com/vercel/next.js/releases)
- [Changelog](https://github.com/vercel/next.js/blob/canary/release.js)
- [Commits](https://github.com/vercel/next.js/commits/v14.1.0/packages/eslint-config-next)

---
updated-dependencies:
- dependency-name: next
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: next
- dependency-name: eslint-config-next
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: next
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-23 14:57:01 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
a31eda8c68 chore(deps): bump date-fns from 3.1.0 to 3.3.1 (#926)
Bumps [date-fns](https://github.com/date-fns/date-fns) from 3.1.0 to 3.3.1.
- [Release notes](https://github.com/date-fns/date-fns/releases)
- [Changelog](https://github.com/date-fns/date-fns/blob/main/CHANGELOG.md)
- [Commits](https://github.com/date-fns/date-fns/compare/v3.1.0...v3.3.1)

---
updated-dependencies:
- dependency-name: date-fns
  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-01-23 15:52:08 +01:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
d044ae51d1 chore(deps-dev): bump @typescript-eslint/parser from 6.16.0 to 6.19.1 (#922)
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 6.16.0 to 6.19.1.
- [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.19.1/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-01-22 22:11:22 +00:00
Marc KlingenandGitHub 552578afc3 fix(ui): improve ui of tag manager (#921) 2024-01-22 21:41:52 +00:00
Marc Klingen 00997db325 chore: release v1.33.10
CI/CD / push-docker-image (push) Blocked by required conditions
CI/CD / tests (18) (push) Failing after 2m38s
CI/CD / tests (20) (push) Failing after 2m2s
CI/CD / test-docker-build (push) Successful in 5m10s
CI/CD / lint (push) Successful in 5m33s
CI/CD / e2e-tests (push) Failing after 2m17s
CI/CD / all-ci-passed (push) Waiting to run
release.yml / release (push) Failing after 3s
2024-01-22 22:17:00 +01:00
Marc KlingenandGitHub 550464cf0b perf: native db upserts for TraceProcessor and ObservationProcessor (#920) 2024-01-22 22:05:48 +01:00
Max DeichmannandGitHub e43568a3d2 fix: send error only in custom sentry alert (#919) 2024-01-22 18:21:17 +00:00
Max DeichmannandGitHub 4869e8a093 fix: remove sentry instrumentation (#918) 2024-01-22 18:16:27 +00:00
Max Deichmann d9b307ec87 chore: release v1.33.9
CI/CD / push-docker-image (push) Blocked by required conditions
CI/CD / tests (18) (push) Failing after 1m16s
CI/CD / tests (20) (push) Failing after 42s
release.yml / release (push) Failing after 3s
CI/CD / e2e-tests (push) Failing after 1m1s
CI/CD / test-docker-build (push) Successful in 3m52s
CI/CD / lint (push) Successful in 4m15s
CI/CD / all-ci-passed (push) Waiting to run
2024-01-22 13:11:40 +01:00
Max Deichmann 3abfbef4c3 refactor: update openapi docs 2024-01-22 13:08:06 +01:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>Max Deichmann
86aa1eb34f chore(deps): bump posthog-js from 1.96.1 to 1.100.0 (#885)
Bumps [posthog-js](https://github.com/PostHog/posthog-js) from 1.96.1 to 1.100.0.
- [Release notes](https://github.com/PostHog/posthog-js/releases)
- [Changelog](https://github.com/PostHog/posthog-js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/PostHog/posthog-js/compare/v1.96.1...v1.100.0)

---
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>
Co-authored-by: Max Deichmann <m.deichmann@tum.de>
2024-01-22 11:35:24 +01:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>Max Deichmann
59edc9851a chore(deps): bump the prisma group with 2 updates (#884)
Bumps the prisma group 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.7.1 to 5.8.1
- [Release notes](https://github.com/prisma/prisma/releases)
- [Commits](https://github.com/prisma/prisma/commits/5.8.1/packages/client)

Updates `prisma` from 5.7.1 to 5.8.1
- [Release notes](https://github.com/prisma/prisma/releases)
- [Commits](https://github.com/prisma/prisma/commits/5.8.1/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-01-22 10:17:09 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
0e31dcef99 chore(deps-dev): bump @typescript-eslint/eslint-plugin from 6.17.0 to 6.19.0 (#887)
chore(deps-dev): bump @typescript-eslint/eslint-plugin

Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 6.17.0 to 6.19.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v6.19.0/packages/eslint-plugin)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  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-01-22 11:12:11 +01:00
Max DeichmannandGitHub a67235ab8a feat: support ordering traces on the GET API (#913) 2024-01-19 13:37:31 +00:00
Max Deichmann eb88c9bdf8 chore: release v1.33.8
CI/CD / push-docker-image (push) Blocked by required conditions
CI/CD / tests (18) (push) Failing after 51s
CI/CD / tests (20) (push) Failing after 44s
release.yml / release (push) Failing after 3s
CI/CD / e2e-tests (push) Failing after 48s
CI/CD / lint (push) Successful in 4m17s
CI/CD / test-docker-build (push) Successful in 4m5s
CI/CD / all-ci-passed (push) Waiting to run
2024-01-19 11:58:20 +01:00
Richard KrümmelandGitHub 77e4791cbe feat(ui): add option to keep tracing side menu open (#912) 2024-01-19 11:54:44 +01:00
Max DeichmannandGitHub 5d922dfae7 fix: filter generations metadata correctly (#911) 2024-01-18 15:35:41 +00:00
Max DeichmannandGitHub c704c84451 fix: fix jsonl export to correctly append output (#909) 2024-01-18 13:14:37 +00:00
Max DeichmannandGitHub 6f23488438 fix: sentry reports only unknown errors (#908) 2024-01-18 12:14:54 +00:00
Max Deichmann ca50abb290 chore: release v1.33.7
CI/CD / push-docker-image (push) Blocked by required conditions
CI/CD / tests (18) (push) Failing after 46s
CI/CD / tests (20) (push) Failing after 42s
CI/CD / e2e-tests (push) Failing after 42s
release.yml / release (push) Failing after 2s
CI/CD / test-docker-build (push) Successful in 3m34s
CI/CD / lint (push) Successful in 4m6s
CI/CD / all-ci-passed (push) Waiting to run
2024-01-17 21:18:44 +01:00
Max DeichmannandGitHub 15067114a2 feat: support array of strings in model parameters (#905) 2024-01-17 20:13:12 +00:00
Max DeichmannandGitHub 645f14535b fic: use encoding once (#904) 2024-01-17 16:58:25 +00:00
Max Deichmann 250a5b03d2 chore: release v1.33.6
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 1m7s
release.yml / release (push) Failing after 3s
CI/CD / test-docker-build (push) Successful in 3m6s
CI/CD / e2e-tests (push) Failing after 48s
CI/CD / lint (push) Successful in 4m1s
CI/CD / all-ci-passed (push) Waiting to run
2024-01-17 16:25:56 +01:00
Max DeichmannandGitHub 5ee060dfc6 refactor: remove external id uniqueness constraint (#903) 2024-01-17 15:24:31 +00:00
Max DeichmannandGitHub f08502cde4 fix: upsert traces on ingestion only on the id (#900) 2024-01-17 13:55:32 +00:00
Max Deichmann 90ecb88249 chore: release v1.33.5
CI/CD / push-docker-image (push) Blocked by required conditions
CI/CD / tests (18) (push) Failing after 48s
CI/CD / tests (20) (push) Failing after 44s
release.yml / release (push) Failing after 2s
CI/CD / e2e-tests (push) Failing after 44s
CI/CD / test-docker-build (push) Successful in 2m47s
CI/CD / lint (push) Successful in 4m15s
CI/CD / all-ci-passed (push) Waiting to run
2024-01-17 14:05:47 +01:00
Max DeichmannandGitHub 16e60f74da fix: capture ingestion errors in sentry (#899) 2024-01-17 12:52:56 +00:00
Max Deichmann 0ab252cc7c chore: release v1.33.3
CI/CD / push-docker-image (push) Blocked by required conditions
CI/CD / tests (18) (push) Failing after 1m10s
CI/CD / tests (20) (push) Failing after 43s
CI/CD / e2e-tests (push) Failing after 42s
release.yml / release (push) Failing after 3s
CI/CD / test-docker-build (push) Successful in 3m39s
CI/CD / lint (push) Successful in 4m7s
CI/CD / all-ci-passed (push) Waiting to run
2024-01-17 13:36:03 +01:00
Max DeichmannandGitHub ebadbaf30d fix: increase ingestion API body size (#898) 2024-01-17 12:23:06 +00:00
Max Deichmann 7ce6b6817e chore: release v1.33.2
CI/CD / push-docker-image (push) Blocked by required conditions
CI/CD / tests (18) (push) Failing after 2m32s
CI/CD / tests (20) (push) Failing after 2m2s
CI/CD / e2e-tests (push) Failing after 2m11s
release.yml / release (push) Failing after 3s
CI/CD / test-docker-build (push) Successful in 5m16s
CI/CD / lint (push) Successful in 5m31s
CI/CD / all-ci-passed (push) Waiting to run
2024-01-17 11:39:23 +01:00
Max DeichmannandGitHub 6d4040d5ed fix: free tiktoken encoder to prevent OOM issues (#897) 2024-01-17 10:32:28 +00:00
Max DeichmannandGitHub 4a7a4c0add feat(infrastructure): add decimal.js support for trpc (#895) 2024-01-16 19:29:29 +01:00
Max Deichmann 883e53d8b5 chore: release v1.33.1
CI/CD / push-docker-image (push) Blocked by required conditions
CI/CD / tests (18) (push) Failing after 2m36s
CI/CD / tests (20) (push) Failing after 2m2s
CI/CD / e2e-tests (push) Failing after 2m14s
CI/CD / lint (push) Successful in 5m48s
CI/CD / test-docker-build (push) Successful in 6m10s
CI/CD / all-ci-passed (push) Waiting to run
release.yml / release (push) Failing after 3s
2024-01-16 18:17:46 +01:00
Richard KrümmelandGitHub a9e6b9ae5c fix: remove tags json view from TracePreview (#894) 2024-01-16 17:12:10 +00:00
Max Deichmann a61ee1f29f chore: release v1.33.0
CI/CD / push-docker-image (push) Blocked by required conditions
CI/CD / tests (18) (push) Failing after 2m50s
CI/CD / tests (20) (push) Failing after 2m2s
CI/CD / test-docker-build (push) Successful in 4m42s
CI/CD / lint (push) Successful in 5m33s
CI/CD / e2e-tests (push) Failing after 2m19s
CI/CD / all-ci-passed (push) Waiting to run
release.yml / release (push) Failing after 3s
2024-01-16 17:44:50 +01:00
Richard KrümmelandGitHub eefdf60e31 feat(ui): add ui for tags on traces (#879) 2024-01-16 17:44:16 +01:00
Max DeichmannandGitHub 19a633a756 fix: add new cost visualisation to trace detail header (#893)
add new cost to traces
2024-01-16 15:49:55 +00:00
Max DeichmannandGitHub e84c1a3ab8 fix: upgrade decimal on export (#892) 2024-01-16 15:32:53 +00:00
Max Deichmann 4d41aa7e53 chore: release v1.32.3
CI/CD / push-docker-image (push) Blocked by required conditions
CI/CD / tests (18) (push) Failing after 2m31s
CI/CD / tests (20) (push) Failing after 2m21s
CI/CD / test-docker-build (push) Successful in 4m44s
CI/CD / e2e-tests (push) Failing after 2m13s
CI/CD / lint (push) Successful in 5m48s
CI/CD / all-ci-passed (push) Waiting to run
release.yml / release (push) Failing after 3s
2024-01-16 16:09:48 +01:00
Max DeichmannandGitHub a4c28cc324 fix: generations table latency (#891) 2024-01-16 15:09:28 +00:00
Max DeichmannandGitHub 187f2e7b1d fix: convert decimals on trpc to number (#890) 2024-01-16 14:50:52 +00:00
Max Deichmann b355825295 chore: release v1.32.2
CI/CD / push-docker-image (push) Blocked by required conditions
CI/CD / tests (18) (push) Failing after 2m37s
CI/CD / tests (20) (push) Failing after 2m4s
CI/CD / e2e-tests (push) Failing after 2m11s
CI/CD / test-docker-build (push) Successful in 5m14s
CI/CD / lint (push) Successful in 5m35s
CI/CD / all-ci-passed (push) Waiting to run
release.yml / release (push) Failing after 4s
2024-01-16 14:47:50 +01:00
Max DeichmannandGitHub 33dc18356a fix: increase decimal places for exports and unify across UI (#889) 2024-01-16 13:35:50 +00:00
Max Deichmann c804d90f6a chore: release v1.32.1
CI/CD / push-docker-image (push) Blocked by required conditions
CI/CD / tests (18) (push) Failing after 2m32s
CI/CD / tests (20) (push) Failing after 2m3s
CI/CD / e2e-tests (push) Failing after 2m11s
CI/CD / test-docker-build (push) Successful in 5m4s
CI/CD / lint (push) Successful in 5m30s
CI/CD / all-ci-passed (push) Waiting to run
release.yml / release (push) Failing after 3s
2024-01-15 19:36:51 +01:00
Max DeichmannandGitHub 09aa547de1 fix: use async sentry span (#883) 2024-01-15 18:35:37 +00:00
Max Deichmann 57839eae5c chore: release v1.32.0
CI/CD / push-docker-image (push) Blocked by required conditions
CI/CD / tests (18) (push) Failing after 2m35s
CI/CD / tests (20) (push) Failing after 2m3s
release.yml / release (push) Failing after 2s
CI/CD / e2e-tests (push) Failing after 2m11s
CI/CD / test-docker-build (push) Successful in 5m4s
CI/CD / lint (push) Successful in 5m33s
CI/CD / all-ci-passed (push) Waiting to run
2024-01-15 19:10:40 +01:00
Max DeichmannandGitHub a43f5f38a1 fix: fix return types on traces router (#882) 2024-01-15 18:09:58 +00:00
8220d07057 feat(ui): add navigation to datasets and dataset items (#871)
* Add DetailPageNav component to Dataset item page

* Add useDetailPageLists hook and useEffect in DatasetItemsTable

* Add useDetailPageLists hook and useEffect in DatasetsTable

* Add DetailPageNav component to Dataset page

* Add DetailPageNav component to DatasetItems

* Add useDetailPageLists hook and useEffect to DatasetRunsTable

* Fix: only show navigation when there is more than one item

* Add DetailPageNav component to DatasetRunItemsTable

* Seed db with two datasets each with two runs and fix CL logging

---------

Co-authored-by: Max Deichmann <m.deichmann@tum.de>
2024-01-15 19:01:40 +01:00
Max Deichmann 89ffe20363 chore: release v1.31.4
CI/CD / push-docker-image (push) Blocked by required conditions
CI/CD / tests (18) (push) Failing after 2m36s
CI/CD / tests (20) (push) Failing after 2m4s
release.yml / release (push) Failing after 2s
CI/CD / e2e-tests (push) Failing after 2m13s
CI/CD / test-docker-build (push) Successful in 5m8s
CI/CD / lint (push) Successful in 5m33s
CI/CD / all-ci-passed (push) Waiting to run
2024-01-15 18:45:23 +01:00
Max DeichmannandGitHub 9a3adf54b1 fix: traces table performance (#881) 2024-01-15 17:44:57 +00:00
Max Deichmann 459129118e chore: release v1.31.3
CI/CD / push-docker-image (push) Blocked by required conditions
CI/CD / tests (18) (push) Failing after 2m32s
CI/CD / tests (20) (push) Failing after 2m2s
release.yml / release (push) Failing after 2s
CI/CD / e2e-tests (push) Failing after 2m8s
CI/CD / test-docker-build (push) Successful in 5m9s
CI/CD / lint (push) Successful in 5m36s
CI/CD / all-ci-passed (push) Waiting to run
2024-01-15 11:26:03 +01:00
Max DeichmannandGitHub 0862370ad6 feat(ui): add time to first token to observation detail view (#878)
add time to first token
2024-01-15 10:25:09 +00:00
Max Deichmann 1bddde99f0 chore: release v1.31.2
CI/CD / push-docker-image (push) Blocked by required conditions
CI/CD / tests (18) (push) Failing after 2m34s
CI/CD / tests (20) (push) Failing after 2m3s
release.yml / release (push) Failing after 3s
CI/CD / e2e-tests (push) Failing after 2m12s
CI/CD / lint (push) Successful in 5m44s
CI/CD / test-docker-build (push) Successful in 5m53s
CI/CD / all-ci-passed (push) Waiting to run
2024-01-11 21:01:07 +01:00
Max DeichmannandGitHub fe2e7681da fix: generations table performance (#872) 2024-01-11 20:50:49 +01:00
Marc Klingen d209766f01 docs: add comment to optimistic update 2024-01-11 18:05:51 +01:00
Richard KrümmelandGitHub 82bfe03dba feat: use react query for optimistic updates (#862) 2024-01-11 16:55:28 +00:00
Marc Klingen 15fc8e4c3c chore: release v1.31.1
CI/CD / push-docker-image (push) Blocked by required conditions
CI/CD / tests (18) (push) Failing after 2m33s
CI/CD / tests (20) (push) Failing after 2m3s
release.yml / release (push) Failing after 3s
CI/CD / e2e-tests (push) Failing after 2m13s
CI/CD / lint (push) Successful in 5m32s
CI/CD / test-docker-build (push) Successful in 6m21s
CI/CD / all-ci-passed (push) Waiting to run
2024-01-11 17:44:18 +01:00
Marc KlingenandGitHub 374dbf9716 feat(tokenization): support alternative model name, gpt-35* instead of gpt-3.5* (#869) 2024-01-11 15:58:16 +00:00
jhlopenandGitHub 6819988f90 perf: return immediately if trace not found (#861) 2024-01-11 15:15:34 +00:00
e3079afb2f fix: assign unique keys to sibling items (#860)
Co-authored-by: Max Deichmann <m.deichmann@tum.de>
2024-01-11 15:10:25 +00:00
HarpinderandGitHub 3b6689f44b fix: correct repo in issue template. (#867)
It pointed to scalar and not langfuse causing confusion while creating issues.
2024-01-11 13:51:45 +01:00
Max DeichmannandGitHub fdf417e961 fix: fix cd pipeline (#863) 2024-01-10 21:18:58 +00:00
Max DeichmannandGitHub a751f1f0f1 refactor: reduce sentry sampling (#858) 2024-01-10 13:57:36 +00:00
Marc KlingenandGitHub 5bf348b55e feat(cloud): add self-serve pricing/checkout page (#857) 2024-01-10 11:39:13 +01:00
Marc Klingen 4ffadc8124 chore: release v1.31.0
CI/CD / push-docker-image (push) Blocked by required conditions
CI/CD / tests (18) (push) Failing after 2m25s
release.yml / release (push) Failing after 2s
CI/CD / tests (20) (push) Failing after 2m20s
CI/CD / e2e-tests (push) Failing after 2m9s
CI/CD / lint (push) Successful in 5m31s
CI/CD / all-ci-passed (push) Waiting to run
2024-01-09 12:01:33 +01:00
Marc KlingenandGitHub 8069fb7ddd feat(cloud): ask new users for referral source, SSO and email/pw (#831) 2024-01-09 10:54:19 +00:00
Marc KlingenandGitHub 133fc90718 feat(ui): nested main navigation for tracing (#834) 2024-01-09 11:50:16 +01:00
Marc KlingenandGitHub 32a2a7956d feat(datasets): delete unused datasets instead of archiving them (#830) 2024-01-09 11:42:38 +01:00
Marc Klingen 01cc9832c1 chore: release v1.30.1
CI/CD / push-docker-image (push) Blocked by required conditions
CI/CD / tests (20) (push) Failing after 2m10s
release.yml / release (push) Failing after 2s
CI/CD / tests (18) (push) Failing after 2m33s
CI/CD / e2e-tests (push) Failing after 2m21s
CI/CD / lint (push) Successful in 5m23s
CI/CD / all-ci-passed (push) Waiting to run
2024-01-09 02:32:58 +01:00
Marc Klingen 6127ea6442 fix: next try to fix docker build problem 2024-01-09 02:22:44 +01:00
Marc Klingen 22fbc2a89d fix: revert 2d8cc2baa3 2024-01-09 02:08:36 +01:00
Marc Klingen 1ed2e230e0 fix: revert to prev @sentry/profiling-node to fix docker build issue 2024-01-09 01:57:42 +01:00
Marc Klingen 6563716f21 chore(deps): bump @sentry/types to fix build issues 2024-01-09 01:03:14 +01:00
Marc KlingenandGitHub 487e0a77d6 fix(ui): scroll behavior of large traces (#846)
fix(ui): scroll behvaior of large traces
2024-01-09 00:00:47 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
c084d42b4a chore(deps): bump lucide-react from 0.306.0 to 0.307.0 (#841)
Bumps [lucide-react](https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react) from 0.306.0 to 0.307.0.
- [Release notes](https://github.com/lucide-icons/lucide/releases)
- [Commits](https://github.com/lucide-icons/lucide/commits/0.307.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-01-08 23:08:01 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2d8cc2baa3 chore(deps): bump the patches group with 4 updates (#839)
Bumps the patches group with 4 updates: [@headlessui/react](https://github.com/tailwindlabs/headlessui/tree/HEAD/packages/@headlessui-react), [@sentry/profiling-node](https://github.com/getsentry/profiling-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 `@headlessui/react` from 1.7.17 to 1.7.18
- [Release notes](https://github.com/tailwindlabs/headlessui/releases)
- [Changelog](https://github.com/tailwindlabs/headlessui/blob/main/packages/@headlessui-react/CHANGELOG.md)
- [Commits](https://github.com/tailwindlabs/headlessui/commits/@headlessui/react@v1.7.18/packages/@headlessui-react)

Updates `@sentry/profiling-node` from 1.3.2 to 1.3.3
- [Release notes](https://github.com/getsentry/profiling-node/releases)
- [Changelog](https://github.com/getsentry/profiling-node/blob/main/CHANGES)
- [Commits](https://github.com/getsentry/profiling-node/compare/v1.3.2...v1.3.3)

Updates `react-hook-form` from 7.49.2 to 7.49.3
- [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.2...v7.49.3)

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

---
updated-dependencies:
- dependency-name: "@headlessui/react"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patches
- dependency-name: "@sentry/profiling-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-01-09 00:03:56 +01:00
Marc Klingen 47630f7c5f chore: issue creation should be enabled 2024-01-08 22:41:06 +01:00
Marc Klingen 082dfaf339 docs: add note on database schema to contributing.md 2024-01-07 17:25:29 +01:00
Max DeichmannandGitHub f8efbd51da style: add db diagram to contributing.md (#833) 2024-01-07 14:13:15 +00:00
Marc Klingen 22d98256ce chore: issue templates 2024-01-06 19:05:27 +01:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
00caa680f2 chore(deps-dev): bump the patches group with 2 updates (#823)
Bumps the patches group with 2 updates: [prettier-plugin-tailwindcss](https://github.com/tailwindlabs/prettier-plugin-tailwindcss) and [tailwindcss](https://github.com/tailwindlabs/tailwindcss).


Updates `prettier-plugin-tailwindcss` from 0.5.10 to 0.5.11
- [Release notes](https://github.com/tailwindlabs/prettier-plugin-tailwindcss/releases)
- [Changelog](https://github.com/tailwindlabs/prettier-plugin-tailwindcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/tailwindlabs/prettier-plugin-tailwindcss/compare/v0.5.10...v0.5.11)

Updates `tailwindcss` from 3.4.0 to 3.4.1
- [Release notes](https://github.com/tailwindlabs/tailwindcss/releases)
- [Changelog](https://github.com/tailwindlabs/tailwindcss/blob/v3.4.1/CHANGELOG.md)
- [Commits](https://github.com/tailwindlabs/tailwindcss/compare/v3.4.0...v3.4.1)

---
updated-dependencies:
- dependency-name: prettier-plugin-tailwindcss
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: patches
- dependency-name: tailwindcss
  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-01-06 02:03:37 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
48d35eb637 chore(deps-dev): bump @typescript-eslint/eslint-plugin from 6.16.0 to 6.17.0 (#824)
chore(deps-dev): bump @typescript-eslint/eslint-plugin

Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 6.16.0 to 6.17.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v6.17.0/packages/eslint-plugin)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  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-01-06 01:56:09 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
61786fedfb chore(deps): bump date-fns from 3.0.6 to 3.1.0 (#825)
Bumps [date-fns](https://github.com/date-fns/date-fns) from 3.0.6 to 3.1.0.
- [Release notes](https://github.com/date-fns/date-fns/releases)
- [Changelog](https://github.com/date-fns/date-fns/blob/main/CHANGELOG.md)
- [Commits](https://github.com/date-fns/date-fns/compare/v3.0.6...v3.1.0)

---
updated-dependencies:
- dependency-name: date-fns
  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-01-06 01:51:47 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
1f3e3603be chore(deps): bump lucide-react from 0.304.0 to 0.306.0 (#826)
Bumps [lucide-react](https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react) from 0.304.0 to 0.306.0.
- [Release notes](https://github.com/lucide-icons/lucide/releases)
- [Commits](https://github.com/lucide-icons/lucide/commits/0.306.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-01-06 01:47:38 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
cee2c797c4 chore(deps): bump @aws-sdk/s3-request-presigner from 3.478.0 to 3.485.0 (#827)
Bumps [@aws-sdk/s3-request-presigner](https://github.com/aws/aws-sdk-js-v3/tree/HEAD/packages/s3-request-presigner) from 3.478.0 to 3.485.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.485.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-01-06 01:43:38 +00:00
538 changed files with 44019 additions and 21071 deletions
+2 -1
View File
@@ -1,3 +1,4 @@
[codespell]
skip = .git,*.pdf,*.svg,package-lock.json,*.prisma
ignore-words-list = afterall
ignore-words-list = afterall,vertx
+13
View File
@@ -16,8 +16,21 @@ 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=
# Set during docker build of application
# Used to disable environment verification at build time
# DOCKER_BUILD=1
+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.
+72 -34
View File
@@ -1,32 +1,75 @@
# 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=
# Exports are streamed to S3 in pages to avoid memory issues
# The page size can be adjusted if needed to optimize performance
# DB_EXPORT_PAGE_SIZE=1000
### 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 +78,19 @@ 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=
# Betterstack
# LANGFUSE_TEAM_BETTERSTACK_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
+3
View File
@@ -0,0 +1,3 @@
node_modules
build
coverage
+11
View File
@@ -0,0 +1,11 @@
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.
+7
View File
@@ -0,0 +1,7 @@
contact_links:
- name: 💡 Feature Request
url: https://github.com/orgs/langfuse/discussions/new?category=ideas
about: Suggest any ideas you have using our discussion forums.
- name: 🤗 Get Help
url: https://github.com/orgs/langfuse/discussions/new?category=support
about: If you cant get something to work the way you expect, open a question in our discussion forums.
@@ -1,36 +0,0 @@
# This template is heavily inspired by the Next.js's template:
# See here: https://github.com/vercel/next.js/blob/canary/.github/ISSUE_TEMPLATE/3.feature_request.yml
name: 🛠 Feature Request
description: Create a feature request for the core packages
title: "feat: "
labels: ["✨ enhancement"]
body:
- type: markdown
attributes:
value: |
Thank you for taking the time to file a feature request. Please fill out this form as completely as possible.
- type: textarea
attributes:
label: Describe the feature you'd like to request
description: Please describe the feature as clear and concise as possible. Remember to add context as to why you believe this feature is needed.
validations:
required: true
- type: textarea
attributes:
label: Describe the solution you'd like to see
description: Please describe the solution you would like to see. Adding example usage is a good way to provide context.
validations:
required: true
- type: textarea
attributes:
label: Additional information
description: Add any other information related to the feature here. If your feature request 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 feature?
options:
- label: Yes, I can implement this and raise a PR
+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
+66 -14
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,40 +28,81 @@ 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
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Build Web Docker image
uses: docker/build-push-action@v4
with:
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:
node-version: [18, 20]
steps:
- name: Set Swap Space
uses: pierotofy/set-swap-space@master
with:
swap-size-gb: 10
- uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
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
@@ -67,6 +115,9 @@ jobs:
run: npm run test
e2e-tests:
defaults:
run:
working-directory: web
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
@@ -74,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
@@ -101,15 +159,17 @@ jobs:
all-ci-passed:
# This allows us to have a branch protection rule for tests and deploys with matrix
runs-on: ubuntu-latest
needs: [lint, tests, e2e-tests]
needs: [lint, tests, e2e-tests, test-docker-build]
if: always()
steps:
- 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
@@ -117,10 +177,6 @@ jobs:
environment: "protected branches"
runs-on: ubuntu-latest
env:
DATABASE_URL: postgresql://postgres:postgres@localhost:5432/postgres
NEXTAUTH_SECRET: "secret"
SALT: "salt"
NEXTAUTH_URL: "http://localhost:3030"
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
permissions:
@@ -132,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
@@ -159,12 +216,7 @@ jobs:
- 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 }}
build-args: |
DATABASE_URL=${{ env.DATABASE_URL }}
NEXTAUTH_SECRET=${{ env.NEXTAUTH_SECRET }}
NEXTAUTH_URL=${{ env.NEXTAUTH_URL }}
SALT=${{ env.SALT }}
+5 -1
View File
@@ -48,4 +48,8 @@ yarn-error.log*
/generated/typescript-server
# openapi spec that is copied during build
/public/openapi*.yml
/public/openapi*.yml
# vscode
.devcontainer
+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"]
}
+47 -16
View File
@@ -2,22 +2,30 @@
First off, thanks for taking the time to contribute! ❤️
Langfuse is an open-source observability and analytics solution for LLM-based applications. We welcome contributions through GitHub pull requests. This document outlines our conventions regarding development workflow, commit message formatting, contact points, and other resources. Our goal is to simplify the process and ensure that your contributions are easily accepted.
The best ways to contribute to Langfuse:
We gratefully welcome improvements to documentation as well as to code.
- Submit and vote on [Ideas](https://github.com/orgs/langfuse/discussions/categories/ideas)
- Create and comment on [Issues](https://github.com/langfuse/langfuse/issues)
- Open a PR.
We welcome contributions through GitHub pull requests. This document outlines our conventions regarding development workflow, commit message formatting, contact points, and other resources. Our goal is to simplify the process and ensure that your contributions are easily accepted.
We gratefully welcome improvements to documentation ([docs repo](https://github.com/langfuse/langfuse-docs)), the core application (this repo) and the SDKs ([Python](https://github.com/langfuse/langfuse-python), [JS](https://github.com/langfuse/langfuse-js)).
The maintainers are available on [Discord](https://langfuse.com/discord) in case you have any questions.
> And if you like the project, but just don't have time to contribute, that's fine. There are other easy ways to support the project and show your appreciation, which we would also be very happy about:
> And if you like the project, but just don't have time to contribute code, that's fine. There are other easy ways to support the project and show your appreciation, which we would also be very happy about:
>
> - Star the project;
> - Tweet about it;
> - Refer to this project in your project's readme;
> - Submit and vote on [Ideas](https://github.com/orgs/langfuse/discussions/categories/ideas);
> - Create and comment on [Issues](https://github.com/langfuse/langfuse/issues);
> - Mention the project at local meetups and tell your friends/colleagues.
## Making a change
_Before making any significant changes, please [open an issue](https://github.com/langfuse/langfuse/issues)._ Discussing your proposed changes ahead of time will make the contribution process smooth for everyone.
_Before making any significant changes, please [open an issue](https://github.com/langfuse/langfuse/issues)._ Discussing your proposed changes ahead of time will make the contribution process smooth for everyone. Large changes that were not discussed in an issue may be rejected.
Once we've discussed your changes and you've got your code ready, make sure that tests are passing and open your pull request.
@@ -79,6 +87,14 @@ flowchart TB
Python --- API
```
### Database Overview
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: [web/prisma/schema.prisma](web/prisma/schema.prisma)
<img src="./web/prisma/database.svg">
### Infrastructure & Network Overview
```mermaid
@@ -94,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
@@ -104,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
@@ -132,7 +163,7 @@ Requirements
# npm run db:seed:examples
```
6. Start the development server
7. Start the development server
```bash
npm run dev
+92 -165
View File
@@ -2,42 +2,43 @@
<a href="https://langfuse.com">
<h1>🪢 Langfuse</h1>
</a>
<div>
<h3> <a href="https://cloud.langfuse.com">
<strong>Sign up</strong>
</a> ·
<a href="https://langfuse.com/docs/deployment/self-host">
<strong>Self Host Langfuse</strong>
</a> ·
<a href="https://langfuse.com/demo">
<strong>Demo Project (live data)</strong>
</a>
</h3>
<h3>
Open source observability & analytics for LLM-based applications
Langfuse is the open source LLM engineering platform.
</h3>
<div>
<strong>Observability:</strong> Explore and debug complex logs & traces in a visual UI
</div>
<div>
<strong>Analytics:</strong> Measure & improve costs, latency and response quality
<div>
Debug, analyze and iterate - together
</div>
</br>
<div>
<a href="https://discord.gg/7NXusRtqYU">
<strong>Join the Langfuse Discord »</strong>
</a>
</br>
<a href="https://langfuse.com">
<strong>langfuse.com</strong>
</a> ·
<a href="https://langfuse.com/docs">
<strong>Docs</strong>
</a> ·
<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+">
<a href="https://langfuse.com/issue">
<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://langfuse.com/idea">
<strong>Feature Request</strong>
</a>
</a> ·
<a href="https://langfuse.com/changelog">
<strong>Changelog</strong>
</a> ·
<a href="https://langfuse.com/discord">
<strong>Discord</strong>
</a>
</div>
</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>
<a href="https://github.com/langfuse/langfuse"><img src="https://img.shields.io/github/stars/langfuse/langfuse?style=flat-square&logo=GitHub&label=langfuse%2Flangfuse" alt="Github Repo Stars"></a>
<a href="https://github.com/langfuse/langfuse/releases"><img src="https://img.shields.io/github/v/release/langfuse/langfuse?include_prereleases&style=flat-square" alt="langfuse releases"></a>
<a href="https://github.com/langfuse/langfuse/actions/workflows/pipeline.yml?query=branch:main"><img src="https://img.shields.io/github/actions/workflow/status/langfuse/langfuse/pipeline.yml?style=flat-square&label=All%20tests" alt="CI test status"></a>
<a href="https://status.langfuse.com"><img src="https://uptime.betterstack.com/status-badges/v1/monitor/udlc.svg" alt="Uptime Status"/></a>
<a href="https://www.ycombinator.com/companies/langfuse"><img src="https://img.shields.io/badge/Y%20Combinator-W23-orange?style=flat-square" alt="Y Combinator W23"></a>
<a href="https://github.com/langfuse/langfuse/pkgs/container/langfuse"><img alt="Docker Image" src="https://img.shields.io/badge/docker-langfuse-blue?logo=Docker&logoColor=white&style=flat-square"></a>
<a href="https://www.npmjs.com/package/langfuse"><img src="https://img.shields.io/npm/v/langfuse?style=flat-square&label=npm+langfuse" alt="langfuse npm package"></a>
@@ -45,61 +46,44 @@
</div>
</div>
</br>
</div>
</br>
## What is Langfuse?
## Overview
Langfuse is an open source observability & analytics solution for LLM-based applications. It is mostly geared towards production usage but some users also use it for local development of their LLM applications.
### Develop
Langfuse is focused on applications built on top of LLMs. Many new abstractions and common best practices evolved recently, e.g. agents, chained prompts, embedding-based retrieval, LLM access to REPLs & APIs. These make applications more powerful but also unpredictable for developers as they cannot fully anticipate how changes impact the quality, cost and overall latency of their application. Thus Langfuse helps to monitor and debug these applications.
- **Observability:** Instrument your app and start ingesting traces to Langfuse ([Quickstart](https://langfuse.com/docs/get-started), [Integrations](https://langfuse.com/docs/integrations) [Tracing](https://langfuse.com/docs/tracing))
- **Langfuse UI:** Inspect and debug complex logs ([Demo](https://langfuse.com/docs/demo), [Tracing](https://langfuse.com/docs/tracing))
- **Prompts:** Manage, version and deploy prompts from within Langfuse ([Prompt Management](https://langfuse.com/docs/prompts))
**Demo (2 min)**
### Monitor
- **Analytics:** Track metrics (cost, latency, quality) and gain insights from dashboards & data exports ([Analytics](https://langfuse.com/docs/analytics))
- **Evals:** Collect and calculate scores for your LLM completions ([Scores & Evaluations](https://langfuse.com/docs/scores))
- Run model-based evaluations ([Model-based evaluations](https://langfuse.com/docs/scores/model-based-evals))
- Collect user feedback ([User Feedback](https://langfuse.com/docs/scores/user-feedback))
- Manually score observations in Langfuse ([Manual Scores](https://langfuse.com/docs/scores/manually))
### Test
- **Experiments:** Track and test app behaviour before deploying a new version
- Datasets let you test expected in and output pairs and benchmark performance before deployiong ([Datasets](https://langfuse.com/docs/datasets))
- Track versions and releases in your application ([Experimentation](https://langfuse.com/docs/experimentation), [Prompt Management](https://langfuse.com/docs/prompts))
### Video: Langfuse in two minutes
https://github.com/langfuse/langfuse/assets/2834609/6041347a-b517-4a11-8737-93ef8f8af49f
_Muted by default, enable sound for voice-over_
Explore demo project in Langfuse here (free account required): https://langfuse.com/demo
### Observability
Langfuse offers an admin UI to explore the ingested data.
- Nested view of LLM app executions; detailed information along the traces on: latency, cost, scores
- Segment execution traces by user feedback, to e.g. identify production issues
### Analytics
Reporting on
- Token usage by model
- Volume of traces
- Scores/evals
Broken down by
- Users
- Releases
- Prompt/chain versions
- Prompt/chain types
- Time
→ Expect releases with more ways to analyze the data over the next weeks.
## Get started
### Step 1: Run Server
### Langfuse Cloud
#### Langfuse Cloud
Managed deployment by the Langfuse team, generous free-tier (hobby plan), no credit card required.
Managed deployment by the Langfuse team, generous free-tier (hobby plan) available, no credit card required.
**[» Langfuse Cloud](https://cloud.langfuse.com)**
Links: [Create account](https://cloud.langfuse.com), [learn more](https://cloud.langfuse.com)
#### Localhost
Requirements: docker, docker compose (e.g. using Docker Desktop)
### Localhost (docker)
```bash
# Clone repository
@@ -110,143 +94,86 @@ cd langfuse
docker compose up -d
```
#### Self-host (Docker)
[→ Learn more about deploying locally](https://langfuse.com/docs/deployment/local)
[→ Instructions](https://langfuse.com/docs/deployment/self-host)
### Self-host (docker)
[![Deploy on Railway](https://railway.app/button.svg)](https://railway.app/template/gmbqa_)
Langfuse is simple to self-host and keep updated. It currently requires only a single docker container.
[→ Self Hosting Instructions](https://langfuse.com/docs/deployment/self-host)
### Step 2: Data ingestion
Templated deployments: [Railway, GCP Cloud Run, AWS Fargate, Kubernetes and others](https://langfuse.com/docs/deployment/self-host#platform-specific-information)
#### SDKs to instrument application
## Get Started
Fully async, typed SDKs to instrument any LLM application. Currently available for Python & JS/TS.
### API Keys
[Guide](https://langfuse.com/docs/guides/sdk-integration) with an example of how the SDK can be used
You require a Langfuse public and secret key to get started. Sign up [here](https://cloud.langfuse.com) and find them in your project settings.
| Package | Description | Links |
| --------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------- | -------------------------------------------------------------------------------------------------------------- |
| [![PyPI Version](https://img.shields.io/pypi/v/langfuse.svg?style=flat-square&label=pypi+langfuse)](https://pypi.python.org/pypi/langfuse) | Python | [docs](https://langfuse.com/docs/integrations/sdk/python), [repo](https://github.com/langfuse/langfuse-python) |
| [![npm Version](https://img.shields.io/npm/v/langfuse?style=flat-square&label=npm+langfuse)](https://www.npmjs.com/package/langfuse) | JS/TS: Node >= 18, Edge runtimes | [docs](https://langfuse.com/docs/integrations/sdk/typescript), [repo](https://github.com/langfuse/langfuse-js) |
| [![npm package](https://img.shields.io/npm/v/langfuse-node?style=flat-square&label=npm+langfuse-node)](https://www.npmjs.com/package/langfuse-node) | JS/TS: Node <18 | [docs](https://langfuse.com/docs/integrations/sdk/typescript), [repo](https://github.com/langfuse/langfuse-js) |
### Ingesting Data · Instrumenting Your Application
#### Langchain applications
Note: We recommend using our fully async, typed [SDKs](https://langfuse.com/docs/sdk) that allow you to instrument any LLM application with any underlying model. They are available in [Python](https://langfuse.com/docs/sdk/python) & [JS/TS](https://langfuse.com/docs/sdk/typescript). The SDKs will always be the most fully featured and stable way to ingest data into Langfuse.
The Langfuse callback handler automatically instruments Langchain applications. Currently available for Python and JS/TS.
You may want to use another integration to get started quickly or implement a use case that we do not yet support. However, we recommend to migrate to the Langfuse SDKs over time to ensure performance and stability.
**Python**
See our the [→ Quickstart](https://langfuse.com/docs/get-started) to get started in integrating Langfuse.
```shell
pip install langfuse
```
### Integrations
```python
# Initialize Langfuse handler
from langfuse.callback import CallbackHandler
handler = CallbackHandler(PUBLIC_KEY, SECRET_KEY)
| 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. |
# Setup Langchain
from langchain.chains import LLMChain
...
chain = LLMChain(llm=llm, prompt=prompt)
External projects/packages that integrate with Langfuse:
# Add Langfuse handler as callback
chain.run(input="<user_input", callbacks=[handler])
```
| 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. |
→ [Langchain integration docs for Python](https://langfuse.com/docs/integrations/langchain/python)
## Questions and feedback
**JS/TS**
### Ideas and roadmap
[Langchain integration docs for JS/TS](https://langfuse.com/docs/integrations/langchain/typescript)
- [GitHub Discussions](https://github.com/orgs/langfuse/discussions)
- [Feature Requests](https://langfuse.com/idea)
#### Add scores/evaluations to traces (optional)
### Support and feedback
Quality/evaluation of traces is tracked via scores ([docs](https://langfuse.com/docs/scores)). Scores are related to traces and optionally to observations. Scores can be added via:
In order of preference the best way to communicate with us:
- **Backend SDKs** (see docs above): `{trace, event, span, generation}.score()`
- **API** (see docs below): `POST /api/public/scores`
- **Client-side using Web SDK**, e.g. to capture user feedback or other user-based quality metrics:
```sh
npm install langfuse
```
```ts
// Client-side (browser)
import { LangfuseWeb } from "langfuse";
const langfuseWeb = new LangfuseWeb({
publicKey: process.env.LANGFUSE_PUBLIC_KEY,
});
// frontend handler (example: React)
export function UserFeedbackComponent(props: { traceId: string }) {
const handleUserFeedback = async (value: number) => {
await langfuseWeb.score({
traceId: props.traceId,
name: "user_feedback",
value,
});
};
return (
<div>
<button onClick={() => handleUserFeedback(1)}>👍</button>
<button onClick={() => handleUserFeedback(-1)}>👎</button>
</div>
);
}
```
#### API
[**Api reference**](https://langfuse.com/docs/integrations/api)
- POST/PATCH routes to ingest data
- GET routes to use data in downstream applications (e.g. embedded analytics)
## Questions / Feedback
The maintainers are very active in the Langfuse [Discord](https://langfuse.com/discord) and are happy to answer questions or discuss feedback/ideas regarding the future of the project.
- [GitHub Discussions](https://github.com/orgs/langfuse/discussions): Contribute [ideas](https://langfuse.com/idea) [support requests](https://github.com/orgs/langfuse/discussions/categories/support) and [report bugs](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+) (preferred as we create a permanent, indexed artifact for other community members)
- [Discord](https://langfuse.com/discord): For community support and to chat directly with maintainers
- Privately: Email contact at langfuse dot com
## Contributing to Langfuse
Join the community [on Discord](https://discord.gg/7NXusRtqYU).
To contribute, send us a PR, raise a GitHub issue, or email at contributing@langfuse.com
### Development setup
See [CONTRIBUTING.md](CONTRIBUTING.md) for details on how to setup a development environment.
- Vote on [Ideas](https://github.com/orgs/langfuse/discussions/categories/ideas)
- Raise and comment on [Issues](https://github.com/langfuse/langfuse/issues)
- Open a PR - see [CONTRIBUTING.md](CONTRIBUTING.md) for details on how to setup a development environment.
## License
Langfuse is MIT licensed, except for `ee/` folder. See [LICENSE](LICENSE) and [docs](https://langfuse.com/docs/open-source) for more details.
This repository is MIT licensed, except for the `ee/` folder. See [LICENSE](LICENSE) and [docs](https://langfuse.com/docs/open-source) for more details.
## Misc
### Upgrade Langfuse (localhost)
### GET API to export your data
```bash
# Stop server and db
docker compose down
[**GET routes**](https://langfuse.com/docs/integrations/api) to use data in downstream applications (e.g. embedded analytics).
# Pull latest changes
git pull
docker-compose pull
### Security & Privacy
# Run server and db
docker compose up -d
```
### Run Langfuse in CI for integration tests
Checkout GitHub Actions workflows of [Python SDK](https://github.com/langfuse/langfuse-python/blob/main/.github/workflows/ci.yml) and [JS/TS SDK](https://github.com/langfuse/langfuse-js/blob/main/.github/workflows/ci.yml).
We take data security and privacy seriously. Please refer to our [Security and Privacy](https://langfuse.com/security) page for more information.
### Telemetry
By default, Langfuse automatically reports basic usage statistics to a centralized server (PostHog).
By default, Langfuse automatically reports basic usage statistics of self-hosted instances to a centralized server (PostHog).
This helps us to:
+36 -8
View File
@@ -1,20 +1,16 @@
version: "3.5"
services:
langfuse-server:
server:
build:
dockerfile: Dockerfile
args:
- DATABASE_URL=postgresql://postgres:postgres@db:5432/postgres
- NEXTAUTH_SECRET=mysecret
- SALT=mysalt
- NEXTAUTH_URL=http://localhost:3000
dockerfile: ./Dockerfile
context: ./web
depends_on:
- db
- redis
ports:
- "3000:3000"
environment:
- NODE_ENV=production
- DATABASE_URL=postgresql://postgres:postgres@db:5432/postgres
- NEXTAUTH_SECRET=mysecret
- SALT=mysalt
@@ -22,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
View File
@@ -8,7 +8,6 @@ services:
ports:
- "3000:3000"
environment:
- NODE_ENV=production
- DATABASE_URL=postgresql://postgres:postgres@db:5432/postgres
- NEXTAUTH_SECRET=mysecret
- SALT=mysalt
+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
+1
View File
@@ -5,6 +5,7 @@ docs: |
- username: Langfuse Public Key
- password: Langfuse Secret Key
error-discrimination:
strategy: status-code
auth: basic
+57 -8
View File
@@ -18,19 +18,34 @@ types:
public:
type: optional<boolean>
docs: Public traces are accessible via url without login
TraceWithDetails:
TraceWithDetails: # GET /traces
extends: Trace
properties:
htmlPath:
type: string
docs: Path of trace in Langfuse UI
latency:
type: double
docs: Latency of trace in seconds
totalCost:
type: double
docs: Cost of trace in USD
observations:
type: list<string>
docs: List of observation ids
scores:
type: list<string>
docs: List of score ids
TraceWithFullDetails:
TraceWithFullDetails: # GET traces/[traceID]
extends: Trace
properties:
observations: list<Observation>
htmlPath:
type: string
docs: Path of trace in Langfuse UI
totalCost:
type: double
docs: Cost of trace in USD
observations: list<ObservationsView>
scores: list<Score>
Session:
properties:
@@ -61,12 +76,42 @@ types:
statusMessage: optional<string>
parentObservationId: optional<string>
promptId: optional<string>
Usage:
ObservationsView:
extends: Observation
properties:
input: optional<integer>
output: optional<integer>
total: optional<integer>
modelId: optional<string>
inputPrice: optional<double>
outputPrice: optional<double>
totalPrice: optional<double>
calculatedInputCost: optional<double>
calculatedOutputCost: optional<double>
calculatedTotalCost: optional<double>
latency: optional<double>
Usage:
docs: Standard interface for usage and cost
properties:
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:
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
@@ -80,7 +125,6 @@ types:
properties:
id: string
name: string
status: DatasetStatus
projectId: string
createdAt: datetime
updatedAt: datetime
@@ -115,9 +159,13 @@ types:
# Utilities
ModelUsageUnit:
docs: Unit of usage in Langfuse
enum:
- CHARACTERS
- TOKENS
- MILLISECONDS
- SECONDS
- IMAGES
ObservationLevel:
enum:
- DEBUG
@@ -130,6 +178,7 @@ types:
- optional<string>
- optional<integer>
- optional<boolean>
- optional<list<string>>
DatasetStatus:
enum:
- ACTIVE
@@ -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
+9 -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>
@@ -128,6 +133,7 @@ types:
TraceBody:
properties:
id: optional<string>
timestamp: optional<datetime>
name: optional<string>
userId: optional<string>
input: optional<unknown>
+48
View File
@@ -0,0 +1,48 @@
# yaml-language-server: $schema=https://raw.githubusercontent.com/fern-api/fern/main/fern.schema.json
imports:
pagination: ./utils/pagination.yml
commons: ./commons.yml
service:
auth: true
base-path: /api/public
endpoints:
daily:
docs: Get daily metrics of the Langfuse project
method: GET
path: /metrics/daily
request:
name: GetDailyMetricsRequest
query-parameters:
page: optional<integer>
limit: optional<integer>
traceName:
type: optional<string>
docs: Optional filter by the name of the trace
userId:
type: optional<string>
docs: Optional filter by the userId associated with the trace
tags:
type: optional<string>
allow-multiple: true
docs: Optional filter for metrics where traces include all of these tags
response: DailyMetrics
types:
DailyMetrics:
properties:
data:
type: list<DailyMetricsDetails>
docs: A list of daily metrics, only days with ingested data are included.
meta: pagination.MetaResponse
DailyMetricsDetails:
properties:
date: date
countTraces: integer
totalCost: double
usage: list<UsageByModel>
UsageByModel:
docs: Daily usage of a given model. Usage corresponds to the unit set for the specific model (e.g. tokens).
properties:
model: string
inputUsage: integer
outputUsage: integer
totalUsage: integer
+8 -3
View File
@@ -7,14 +7,14 @@ service:
base-path: /api/public
endpoints:
get:
docs: Get a specific observation
docs: Get a observation
method: GET
path: /observations/{observationId}
path-parameters:
observationId:
type: string
docs: The unique langfuse identifier of an observation, can be an event, span or generation
response: commons.Observation
response: commons.ObservationsView
getMany:
docs: Get a list of observations
method: GET
@@ -29,10 +29,15 @@ service:
type: optional<string>
traceId: optional<string>
parentObservationId: optional<string>
response: Observations
response: ObservationsViews
types:
Observations:
properties:
data: list<commons.Observation>
meta: pagination.MetaResponse
ObservationsViews:
properties:
data: list<commons.ObservationsView>
meta: pagination.MetaResponse
+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
+8 -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,10 +27,15 @@ types:
CreatePromptRequest:
properties:
name: string
isActive: boolean
isActive:
docs: Should the prompt be promoted to production immediately?
type: boolean
prompt: string
config: optional<unknown>
Prompt:
properties:
name: string
version: integer
prompt: string
config: unknown
+19 -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,23 @@ 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
path: /scores/{scoreId}
path-parameters:
scoreId:
type: string
docs: The unique langfuse identifier of a score
types:
CreateScoreRequest:
properties:
+6
View File
@@ -26,6 +26,9 @@ service:
limit: optional<integer>
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)
tags:
type: optional<string>
allow-multiple: true
@@ -37,3 +40,6 @@ types:
properties:
data: list<commons.TraceWithDetails>
meta: pagination.MetaResponse
Sort:
properties:
id: string
+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
+1 -1
View File
@@ -1,4 +1,4 @@
{
"organization": "finto",
"version": "0.16.22"
"version": "0.16.36"
}
+290 -6
View File
@@ -387,6 +387,81 @@ paths:
$ref: '#/components/schemas/IngestionEvent'
required:
- batch
/api/public/metrics/daily:
get:
description: Get daily metrics of the Langfuse project
operationId: metrics_daily
tags:
- Metrics
parameters:
- name: page
in: query
required: false
schema:
type: integer
nullable: true
- name: limit
in: query
required: false
schema:
type: integer
nullable: true
- name: traceName
in: query
description: Optional filter by the name of the trace
required: false
schema:
type: string
nullable: true
- name: userId
in: query
description: Optional filter by the userId associated with the trace
required: false
schema:
type: string
nullable: true
- name: tags
in: query
description: Optional filter for metrics where traces include all of these tags
required: false
schema:
type: array
items:
type: string
nullable: true
responses:
'200':
description: ''
content:
application/json:
schema:
$ref: '#/components/schemas/DailyMetrics'
'400':
description: ''
content:
application/json:
schema: {}
'401':
description: ''
content:
application/json:
schema: {}
'403':
description: ''
content:
application/json:
schema: {}
'404':
description: ''
content:
application/json:
schema: {}
'405':
description: ''
content:
application/json:
schema: {}
security: *ref_0
/api/public/observations/{observationId}:
get:
description: Get a specific observation
@@ -408,7 +483,7 @@ paths:
content:
application/json:
schema:
$ref: '#/components/schemas/Observation'
$ref: '#/components/schemas/ObservationsView'
'400':
description: ''
content:
@@ -490,7 +565,7 @@ paths:
content:
application/json:
schema:
$ref: '#/components/schemas/Observations'
$ref: '#/components/schemas/ObservationsViews'
'400':
description: ''
content:
@@ -761,6 +836,48 @@ paths:
application/json:
schema: {}
security: *ref_0
/api/public/scores/{scoreId}:
delete:
description: Delete a score
operationId: score_delete
tags:
- Score
parameters:
- name: scoreId
in: path
description: The unique langfuse identifier of a score
required: true
schema:
type: string
responses:
'204':
description: ''
'400':
description: ''
content:
application/json:
schema: {}
'401':
description: ''
content:
application/json:
schema: {}
'403':
description: ''
content:
application/json:
schema: {}
'404':
description: ''
content:
application/json:
schema: {}
'405':
description: ''
content:
application/json:
schema: {}
security: *ref_0
/api/public/sessions/{sessionId}:
get:
description: Get a session
@@ -884,6 +1001,14 @@ paths:
schema:
type: string
nullable: true
- name: orderBy
in: query
description: >-
Format of the string sort_by=timestamp.asc (id, timestamp, name,
userId, release, version, public, bookmarked, sessionId)
required: true
schema:
type: string
- name: tags
in: query
description: Only traces that include all of these tags will be returned.
@@ -975,6 +1100,17 @@ components:
title: TraceWithDetails
type: object
properties:
htmlPath:
type: string
description: Path of trace in Langfuse UI
latency:
type: number
format: double
description: Latency of trace in seconds
totalCost:
type: number
format: double
description: Cost of trace in USD
observations:
type: array
items:
@@ -986,6 +1122,9 @@ components:
type: string
description: List of score ids
required:
- htmlPath
- latency
- totalCost
- observations
- scores
allOf:
@@ -994,15 +1133,24 @@ components:
title: TraceWithFullDetails
type: object
properties:
htmlPath:
type: string
description: Path of trace in Langfuse UI
totalCost:
type: number
format: double
description: Cost of trace in USD
observations:
type: array
items:
$ref: '#/components/schemas/Observation'
$ref: '#/components/schemas/ObservationsView'
scores:
type: array
items:
$ref: '#/components/schemas/Score'
required:
- htmlPath
- totalCost
- observations
- scores
allOf:
@@ -1095,6 +1243,43 @@ components:
- type
- startTime
- level
ObservationsView:
title: ObservationsView
type: object
properties:
modelId:
type: string
nullable: true
inputPrice:
type: number
format: double
nullable: true
outputPrice:
type: number
format: double
nullable: true
totalPrice:
type: number
format: double
nullable: true
calculatedInputCost:
type: number
format: double
nullable: true
calculatedOutputCost:
type: number
format: double
nullable: true
calculatedTotalCost:
type: number
format: double
nullable: true
latency:
type: number
format: double
nullable: true
allOf:
- $ref: '#/components/schemas/Observation'
Usage:
title: Usage
type: object
@@ -1111,6 +1296,18 @@ components:
unit:
$ref: '#/components/schemas/ModelUsageUnit'
nullable: true
inputCost:
type: number
format: double
nullable: true
outputCost:
type: number
format: double
nullable: true
totalCost:
type: number
format: double
nullable: true
Score:
title: Score
type: object
@@ -1147,8 +1344,6 @@ components:
type: string
name:
type: string
status:
$ref: '#/components/schemas/DatasetStatus'
projectId:
type: string
createdAt:
@@ -1168,7 +1363,6 @@ components:
required:
- id
- name
- status
- projectId
- createdAt
- updatedAt
@@ -1261,6 +1455,9 @@ components:
enum:
- CHARACTERS
- TOKENS
- MILLISECONDS
- SECONDS
- IMAGES
ObservationLevel:
title: ObservationLevel
type: string
@@ -1278,6 +1475,10 @@ components:
nullable: true
- type: boolean
nullable: true
- type: array
items:
type: string
nullable: true
DatasetStatus:
title: DatasetStatus
type: string
@@ -1663,6 +1864,10 @@ components:
id:
type: string
nullable: true
timestamp:
type: string
format: date-time
nullable: true
name:
type: string
nullable: true
@@ -1879,6 +2084,60 @@ components:
required:
- successes
- errors
DailyMetrics:
title: DailyMetrics
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/DailyMetricsDetails'
description: A list of daily metrics, only days with ingested data are included.
meta:
$ref: '#/components/schemas/utilsMetaResponse'
required:
- data
- meta
DailyMetricsDetails:
title: DailyMetricsDetails
type: object
properties:
date:
type: string
countTraces:
type: integer
totalCost:
type: number
format: double
usage:
type: array
items:
$ref: '#/components/schemas/UsageByModel'
required:
- date
- countTraces
- totalCost
- usage
UsageByModel:
title: UsageByModel
type: object
description: >-
Daily usage of a given model. Usage corresponds to the unit set for the
specific model (e.g. tokens).
properties:
model:
type: string
inputUsage:
type: integer
outputUsage:
type: integer
totalUsage:
type: integer
required:
- model
- inputUsage
- outputUsage
- totalUsage
Observations:
title: Observations
type: object
@@ -1892,6 +2151,19 @@ components:
required:
- data
- meta
ObservationsViews:
title: ObservationsViews
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/ObservationsView'
meta:
$ref: '#/components/schemas/utilsMetaResponse'
required:
- data
- meta
Projects:
title: Projects
type: object
@@ -1923,6 +2195,8 @@ components:
type: boolean
prompt:
type: string
config:
nullable: true
required:
- name
- isActive
@@ -1937,10 +2211,12 @@ components:
type: integer
prompt:
type: string
config: {}
required:
- name
- version
- prompt
- config
CreateScoreRequest:
title: CreateScoreRequest
type: object
@@ -1991,6 +2267,14 @@ components:
required:
- data
- meta
Sort:
title: Sort
type: object
properties:
id:
type: string
required:
- id
utilsMetaResponse:
title: utilsMetaResponse
type: object
+140 -12
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": [
@@ -320,7 +320,7 @@
"auth": null,
"body": {
"mode": "raw",
"raw": "{\n \"batch\": [\n {\n \"type\": \"trace-create\",\n \"body\": {\n \"id\": \"example\",\n \"name\": \"example\",\n \"userId\": \"example\",\n \"input\": \"UNKNOWN\",\n \"output\": \"UNKNOWN\",\n \"sessionId\": \"example\",\n \"release\": \"example\",\n \"version\": \"example\",\n \"metadata\": \"UNKNOWN\",\n \"tags\": [\n \"example\"\n ],\n \"public\": true\n },\n \"id\": \"example\",\n \"timestamp\": \"example\",\n \"metadata\": \"UNKNOWN\"\n }\n ]\n}",
"raw": "{\n \"batch\": [\n {\n \"type\": \"trace-create\",\n \"body\": {\n \"id\": \"example\",\n \"timestamp\": \"1994-11-05T13:15:30Z\",\n \"name\": \"example\",\n \"userId\": \"example\",\n \"input\": \"UNKNOWN\",\n \"output\": \"UNKNOWN\",\n \"sessionId\": \"example\",\n \"release\": \"example\",\n \"version\": \"example\",\n \"metadata\": \"UNKNOWN\",\n \"tags\": [\n \"example\"\n ],\n \"public\": true\n },\n \"id\": \"example\",\n \"timestamp\": \"example\",\n \"metadata\": \"UNKNOWN\"\n }\n ]\n}",
"options": {
"raw": {
"language": "json"
@@ -332,6 +332,65 @@
}
]
},
{
"_type": "container",
"description": null,
"name": "Metrics",
"item": [
{
"_type": "endpoint",
"name": "Daily",
"request": {
"description": "Get daily metrics of the Langfuse project",
"url": {
"raw": "{{baseUrl}}/api/public/metrics/daily?page=&limit=&traceName=&userId=&tags=",
"host": [
"{{baseUrl}}"
],
"path": [
"api",
"public",
"metrics",
"daily"
],
"query": [
{
"key": "page",
"value": "",
"description": null
},
{
"key": "limit",
"value": "",
"description": null
},
{
"key": "traceName",
"value": "",
"description": "Optional filter by the name of the trace"
},
{
"key": "userId",
"value": "",
"description": "Optional filter by the userId associated with the trace"
},
{
"key": "tags",
"value": "",
"description": "Optional filter for metrics where traces include all of these tags"
}
],
"variable": []
},
"header": [],
"method": "GET",
"auth": null,
"body": null
},
"response": []
}
]
},
{
"_type": "container",
"description": null,
@@ -341,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": [
@@ -441,7 +500,7 @@
"_type": "endpoint",
"name": "Get",
"request": {
"description": null,
"description": "Get Project associated with API key",
"url": {
"raw": "{{baseUrl}}/api/public/projects",
"host": [
@@ -473,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": [
@@ -509,7 +568,7 @@
"_type": "endpoint",
"name": "Create",
"request": {
"description": "Create a specific prompt",
"description": "Create a prompt",
"url": {
"raw": "{{baseUrl}}/api/public/prompts",
"host": [
@@ -528,7 +587,7 @@
"auth": null,
"body": {
"mode": "raw",
"raw": "{\n \"name\": \"example\",\n \"isActive\": true,\n \"prompt\": \"example\"\n}",
"raw": "{\n \"name\": \"example\",\n \"isActive\": true,\n \"prompt\": \"example\",\n \"config\": \"UNKNOWN\"\n}",
"options": {
"raw": {
"language": "json"
@@ -549,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": [
@@ -582,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": [
@@ -623,6 +682,70 @@
"body": null
},
"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",
"request": {
"description": "Delete 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": "DELETE",
"auth": null,
"body": null
},
"response": []
}
]
},
@@ -708,7 +831,7 @@
"request": {
"description": "Get list of traces",
"url": {
"raw": "{{baseUrl}}/api/public/traces?page=&limit=&userId=&name=&tags=",
"raw": "{{baseUrl}}/api/public/traces?page=&limit=&userId=&name=&orderBy=&tags=",
"host": [
"{{baseUrl}}"
],
@@ -738,6 +861,11 @@
"value": "",
"description": null
},
{
"key": "orderBy",
"value": "",
"description": "Format of the string sort_by=timestamp.asc (id, timestamp, name, userId, release, version, public, bookmarked, sessionId)"
},
{
"key": "tags",
"value": "",
+213 -16037
View File
File diff suppressed because it is too large Load Diff
+14 -160
View File
@@ -1,168 +1,22 @@
{
"name": "langfuse-core",
"version": "1.30.0",
"private": true,
"name": "langfuse",
"version": "2.7.0",
"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",
"db:migrate": "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"
},
"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.485.0",
"@aws-sdk/s3-request-presigner": "^3.478.0",
"@headlessui/react": "^1.7.17",
"@heroicons/react": "^2.1.1",
"@hookform/resolvers": "^3.3.4",
"@next-auth/prisma-adapter": "^1.0.7",
"@prisma/client": "^5.7.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-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.12",
"@react-email/render": "^0.0.10",
"@sentry/nextjs": "^7.92.0",
"@sentry/profiling-node": "^1.3.2",
"@sentry/types": "^7.88.0",
"@t3-oss/env-nextjs": "^0.7.1",
"@tailwindcss/forms": "^0.5.7",
"@tanstack/react-query": "^4.36.1",
"@tanstack/react-table": "^8.11.3",
"@tremor/react": "^3.11.1",
"@trpc/client": "^10.44.1",
"@trpc/next": "^10.44.1",
"@trpc/react-query": "^10.44.1",
"@trpc/server": "^10.44.1",
"@vercel/edge-config": "^0.4.1",
"bcryptjs": "^2.4.3",
"class-variance-authority": "^0.7.0",
"clsx": "^2.0.0",
"cmdk": "^0.2.0",
"core-js": "^3.35.0",
"cors": "^2.8.5",
"date-fns": "^3.0.6",
"decimal.js": "^10.4.3",
"exponential-backoff": "^3.1.1",
"lodash": "^4.17.21",
"lucide-react": "^0.304.0",
"next": "^14.0.4",
"next-auth": "^4.24.5",
"next-query-params": "^5.0.0",
"nodemailer": "^6.9.8",
"posthog-js": "^1.96.1",
"posthog-node": "^3.2.1",
"react": "18.2.0",
"react-day-picker": "^8.10.0",
"react-dom": "18.2.0",
"react-hook-form": "^7.49.2",
"react-icons": "^4.12.0",
"react-responsive": "^9.0.2",
"react18-json-view": "^0.2.7-canary.2",
"superjson": "2.2.1",
"tailwind-merge": "^2.2.0",
"tailwindcss-animate": "^1.0.7",
"tiktoken": "^1.0.11",
"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",
"@playwright/test": "^1.40.1",
"@release-it/bumper": "^6.0.1",
"@testing-library/jest-dom": "^6.1.5",
"@testing-library/react": "^14.1.2",
"@types/bcryptjs": "^2.4.6",
"@types/cors": "^2.8.17",
"@types/eslint": "^8.56.1",
"@types/jest": "^29.5.11",
"@types/lodash": "^4.14.202",
"@types/node": "20.10.5",
"@types/nodemailer": "^6.4.14",
"@types/react": "^18.2.46",
"@types/react-dom": "^18.2.18",
"@types/uuid": "^9.0.7",
"@typescript-eslint/eslint-plugin": "^6.16.0",
"@typescript-eslint/parser": "^6.16.0",
"autoprefixer": "^10.4.16",
"@types/eslint": "^8.56.2",
"@types/jest": "^29.5.12",
"@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.0.4",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
"postcss": "^8.4.33",
"prettier": "^3.1.1",
"prettier-plugin-tailwindcss": "^0.5.10",
"prisma": "^5.7.1",
"release-it": "^17.0.1",
"tailwindcss": "^3.4.0",
"ts-node": "^10.9.2",
"tsconfig-paths": "^4.2.0",
"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"
}
}
-465
View File
@@ -1,465 +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";
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.create({
data: {
id: "239ad00f-562f-411d-af14-831c75ddd875",
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,
},
},
},
});
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 % 10 === 0) {
process.stdout.clearLine(0);
process.stdout.cursorTo(0);
process.stdout.write(`Seeding ${i} 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 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`,
},
tags: tags as string[],
project: {
connect: {
id: [project1.id, project2.id][i % 2],
},
},
userId: `user-${i % 10}`,
session:
Math.random() > 0.3
? {
connectOrCreate: {
where: {
id: `session-${i % 10}`,
},
create: {
id: `session-${i % 10}`,
project: {
connect: { id: [project1.id, project2.id][i % 2] },
},
},
},
}
: 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 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 } },
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: Math.random() > 0.5 ? "gpt-3.5-turbo" : "gpt-4",
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 } } }
: {}),
},
},
});
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 } },
},
});
}
}
}
}
const dataset = await prisma.dataset.create({
data: {
name: "demo-dataset",
projectId: project2.id,
},
});
const datasetRun = await prisma.datasetRuns.create({
data: {
name: "demo-dataset-run",
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

-117
View File
@@ -1,117 +0,0 @@
import { tokenCount } from "@/src/features/ingest/lib/usage";
describe("Token Count Functions", () => {
describe("token count for strings", () => {
[
{ model: "gpt-3.5", tokens: 114 },
{ model: "gpt-4-1106-preview", tokens: 114 },
{ model: "gpt-4-vision-preview", tokens: 114 },
{ model: "claude", tokens: 118 },
{ model: "claude-instant-1.2", tokens: 118 },
{ model: "gpt-3.5-turbo-1106", tokens: 114 },
].forEach(({ model, tokens }) => {
it(`should return token count ${tokens} for ${model}`, () => {
const result = tokenCount({
model: model,
text: "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.",
});
expect(result).toBeDefined();
expect(result).toBe(tokens);
});
});
it("should return undefined for unknown model", () => {
const result = tokenCount({
model: "unknown-model",
text: "Hello, World!",
});
expect(result).toBeUndefined();
});
it("should return for invalid text type", () => {
const result = tokenCount({ model: "gpt-4", text: 1234 });
expect(result).toBe(2);
});
it("should return correct token count for empty string", () => {
const result = tokenCount({
model: "gpt-4",
text: "",
});
expect(result).toBe(0);
});
it("should return correct token count for very long string", () => {
const longString = "A".repeat(10000);
const result = tokenCount({
model: "gpt-4",
text: longString,
});
expect(result).toBeDefined();
expect(result).toBe(1250);
});
it("should return undefined for null text input", () => {
const result = tokenCount({
model: "gpt-4",
text: null,
});
expect(result).toBeUndefined();
});
it("should return undefined for undefined text input", () => {
const result = tokenCount({
model: "gpt-4",
text: undefined,
});
expect(result).toBeUndefined();
});
});
describe("token count for chat messages", () => {
[
{ model: "gpt-4", tokens: 44 },
{ model: "gpt-3.5-turbo-16k-0613", tokens: 44 },
{ model: "claude-instant-1.2", tokens: 48 },
].forEach(({ model, tokens }) => {
it(`should return token count ${tokens} for ${model}`, () => {
const result = tokenCount({
model: model,
text: [
{ role: "system", content: "You are a helpful assistant." },
{ role: "user", content: "Who won the world series in 2020?" },
{
role: "assistant",
content: "The Los Angeles Dodgers won the World Series in 2020.",
},
],
});
expect(result).toBeDefined();
expect(result).toBe(tokens);
});
});
it("should return for non array", () => {
const result = tokenCount({
model: "gpt-4",
text: { role: "Helo world" },
});
expect(result).toBe(7);
});
it("should return for empty array", () => {
const result = tokenCount({
model: "gpt-4",
text: [],
});
expect(result).toBeUndefined();
});
it("should return for array of invalid object", () => {
const result = tokenCount({
model: "gpt-4",
text: [{ role: "Helo world" }],
});
expect(result).toBe(9);
});
});
});
-52
View File
@@ -1,52 +0,0 @@
import { VERSION } from "@/src/constants/VERSION";
import { cn } from "@/src/utils/tailwind";
export const LangfuseIcon = ({
size = 32,
className,
}: {
size?: number;
className?: string;
}) => (
// eslint-disable-next-line @next/next/no-img-element
<img
src="/icon256.png"
width={size}
height={size}
alt="Langfuse Icon"
className={className}
/>
);
export const LangfuseLogo = ({
className,
size = "sm",
version = false,
}: {
size?: "sm" | "xl";
className?: string;
version?: boolean;
}) => (
<div className={cn("flex items-center", className)}>
<LangfuseIcon size={size === "sm" ? 16 : 20} />
<span
className={cn(
"font-mono font-semibold",
size === "sm" ? "ml-2 text-sm" : "ml-3 text-xl",
)}
>
Langfuse
</span>
{version && (
<a
href="https://github.com/langfuse/langfuse/releases"
target="_blank"
rel="noopener"
title="View releases on GitHub"
className="ml-2 text-xs text-gray-400"
>
{VERSION}
</a>
)}
</div>
);
-122
View File
@@ -1,122 +0,0 @@
import { StarIcon } from "lucide-react";
import { Button } from "@/src/components/ui/button";
import { useEffect, useState } from "react";
import { api } from "@/src/utils/api";
import { useHasAccess } from "@/src/features/rbac/utils/checkAccess";
import { cn } from "@/src/utils/tailwind";
export function StarToggle({
value,
disabled = false,
onClick,
size = "sm",
}: {
value: boolean;
disabled?: boolean;
onClick: (value: boolean) => Promise<unknown>;
size?: "sm" | "xs";
}) {
const [cachedValue, setCachedValue] = useState<boolean | null>(null);
const [loading, setLoading] = useState(false);
const optimisticValue = cachedValue ?? value;
useEffect(() => {
setCachedValue(null);
}, [value]);
const handleBookmarkClick = async () => {
if (disabled) return;
setLoading(true);
setCachedValue(!optimisticValue);
await onClick(!optimisticValue);
setLoading(false);
};
return (
<Button
variant="ghost"
size={size}
onClick={() => void handleBookmarkClick()}
disabled={disabled}
loading={loading}
>
<StarIcon
className={cn(
"h-4 w-4",
optimisticValue ? "fill-current text-yellow-500" : "text-gray-500",
)}
/>
</Button>
);
}
export function StarTraceToggle({
projectId,
traceId,
value,
size = "sm",
}: {
projectId: string;
traceId: string;
value: boolean;
size?: "sm" | "xs";
}) {
const utils = api.useUtils();
const hasAccess = useHasAccess({ projectId, scope: "objects:bookmark" });
const mutBookmarkTrace = api.traces.bookmark.useMutation({
onSuccess: () => {
void utils.traces.invalidate();
},
});
return (
<StarToggle
value={value}
size={size}
disabled={!hasAccess}
onClick={(value) =>
mutBookmarkTrace.mutateAsync({
projectId,
traceId,
bookmarked: value,
})
}
/>
);
}
export function StarSessionToggle({
projectId,
sessionId,
value,
size = "sm",
}: {
projectId: string;
sessionId: string;
value: boolean;
size?: "sm" | "xs";
}) {
const utils = api.useUtils();
const hasAccess = useHasAccess({ projectId, scope: "objects:bookmark" });
const mutBookmarkSession = api.sessions.bookmark.useMutation({
onSuccess: () => {
void utils.sessions.invalidate();
},
});
return (
<StarToggle
value={value}
size={size}
disabled={!hasAccess}
onClick={(value) =>
mutBookmarkSession.mutateAsync({
projectId,
sessionId,
bookmarked: value,
})
}
/>
);
}
-215
View File
@@ -1,215 +0,0 @@
import { type NestedObservation } from "@/src/utils/types";
import { cn } from "@/src/utils/tailwind";
import { type Trace, type Score } from "@prisma/client";
import { GroupedScoreBadges } from "@/src/components/grouped-score-badge";
import { Fragment } from "react";
import { type ObservationReturnType } from "@/src/server/api/routers/traces";
import { LevelColors } from "@/src/components/level-colors";
import { formatInterval } from "@/src/utils/dates";
export const ObservationTree = (props: {
observations: ObservationReturnType[];
trace: Trace;
scores: Score[];
currentObservationId: string | undefined;
setCurrentObservationId: (id: string | undefined) => void;
showMetrics: boolean;
showScores: boolean;
className?: string;
}) => {
const nestedObservations = nestObservations(props.observations);
return (
<div className={props.className}>
<ObservationTreeTraceNode
trace={props.trace}
scores={props.scores}
currentObservationId={props.currentObservationId}
setCurrentObservationId={props.setCurrentObservationId}
showMetrics={props.showMetrics}
showScores={props.showScores}
/>
<ObservationTreeNode
observations={nestedObservations}
scores={props.scores}
indentationLevel={1}
currentObservationId={props.currentObservationId}
setCurrentObservationId={props.setCurrentObservationId}
showMetrics={props.showMetrics}
showScores={props.showScores}
/>
</div>
);
};
const ObservationTreeTraceNode = (props: {
trace: Trace & { latency?: number };
scores: Score[];
currentObservationId: string | undefined;
setCurrentObservationId: (id: string | undefined) => void;
showMetrics?: boolean;
showScores?: boolean;
}) => (
<div
className={cn(
"group mb-0.5 flex cursor-pointer flex-col gap-1 rounded-sm p-1.5",
props.currentObservationId === undefined ||
props.currentObservationId === ""
? "bg-gray-100"
: "hover:bg-gray-50",
)}
onClick={() => props.setCurrentObservationId(undefined)}
>
<div className="flex gap-2">
<span className={cn("rounded-sm bg-gray-200 p-1 text-xs")}>TRACE</span>
<span className="text-sm">{props.trace.name}</span>
</div>
{props.showMetrics && props.trace.latency ? (
<div className="flex gap-2">
<span className="text-xs text-gray-500">
{formatInterval(props.trace.latency)}
</span>
</div>
) : null}
{props.showScores && props.scores.find((s) => s.observationId === null) ? (
<div className="flex flex-wrap gap-1">
<GroupedScoreBadges
scores={props.scores.filter((s) => s.observationId === null)}
/>
</div>
) : null}
</div>
);
const ObservationTreeNode = (props: {
observations: NestedObservation[];
scores: Score[];
indentationLevel: number;
currentObservationId: string | undefined;
setCurrentObservationId: (id: string | undefined) => void;
showMetrics?: boolean;
showScores?: boolean;
}) => (
<>
{props.observations
.sort((a, b) => a.startTime.getTime() - b.startTime.getTime())
.map((observation) => (
<Fragment key={observation.id}>
<div className="flex">
{Array.from({ length: props.indentationLevel }, (_, i) => (
<div className="mx-2 border-r" key={i} />
))}
<div
className={cn(
"group my-0.5 flex flex-1 cursor-pointer flex-col gap-1 rounded-sm p-1.5",
props.currentObservationId === observation.id
? "bg-gray-100"
: "hover:bg-gray-50",
)}
onClick={() => props.setCurrentObservationId(observation.id)}
>
<div className="flex gap-2">
<span
className={cn(
"self-start rounded-sm bg-gray-200 p-1 text-xs",
)}
>
{observation.type}
</span>
<span className="line-clamp-1 text-sm">{observation.name}</span>
</div>
{props.showMetrics &&
(observation.promptTokens ||
observation.completionTokens ||
observation.totalTokens ||
observation.endTime) && (
<div className="flex gap-2">
{observation.endTime ? (
<span className="text-xs text-gray-500">
{formatInterval(
(observation.endTime.getTime() -
observation.startTime.getTime()) /
1000,
)}
</span>
) : null}
{observation.promptTokens ||
observation.completionTokens ||
observation.totalTokens ? (
<span className="text-xs text-gray-500">
{observation.promptTokens} {" "}
{observation.completionTokens} ({" "}
{observation.totalTokens})
</span>
) : null}
</div>
)}
{observation.level !== "DEFAULT" ? (
<div className="flex">
<span
className={cn(
"rounded-sm p-0.5 text-xs",
LevelColors[observation.level].bg,
LevelColors[observation.level].text,
)}
>
{observation.level}
</span>
</div>
) : null}
{props.showScores &&
props.scores.find((s) => s.observationId === observation.id) ? (
<div className="flex flex-wrap gap-1">
<GroupedScoreBadges
scores={props.scores.filter(
(s) => s.observationId === observation.id,
)}
/>
</div>
) : null}
</div>
</div>
<ObservationTreeNode
observations={observation.children}
scores={props.scores}
indentationLevel={props.indentationLevel + 1}
currentObservationId={props.currentObservationId}
setCurrentObservationId={props.setCurrentObservationId}
showMetrics={props.showMetrics}
showScores={props.showScores}
/>
</Fragment>
))}
</>
);
export function nestObservations(
list: ObservationReturnType[],
): NestedObservation[] {
if (list.length === 0) return [];
// Step 1: Create a map where the keys are object IDs, and the values are
// the corresponding objects with an added 'children' property.
const map = new Map<string, NestedObservation>();
for (const obj of list) {
map.set(obj.id, { ...obj, children: [] });
}
// Step 2: Create another map for the roots of all trees.
const roots = new Map<string, NestedObservation>();
// Step 3: Populate the 'children' arrays and root map.
for (const obj of map.values()) {
if (obj.parentObservationId) {
const parent = map.get(obj.parentObservationId);
if (parent) {
parent.children.push(obj);
}
} else {
roots.set(obj.id, obj);
}
}
// TODO sum token amounts per level
// Step 4: Return the roots.
return Array.from(roots.values());
}
-1
View File
@@ -1 +0,0 @@
export const VERSION = "v1.30.0";
@@ -1,69 +0,0 @@
import { useState, useEffect } from "react";
import { type VisibilityState } from "@tanstack/react-table";
import { type LangfuseColumnDef } from "@/src/components/table/types";
function useColumnVisibility<TData>(
localStorageKey: string,
columns: LangfuseColumnDef<TData>[],
) {
const [columnVisibility, setColumnVisibility] = useState<VisibilityState>(
() => {
try {
const savedVisibility = localStorage.getItem(localStorageKey);
const visibilityState: VisibilityState = savedVisibility
? (JSON.parse(savedVisibility) as VisibilityState)
: {};
// set default visibility for columns that are not in the saved state
columns.forEach((column) => {
if (
"accessorKey" in column &&
typeof column.accessorKey === "string"
) {
if (!(column.accessorKey in visibilityState)) {
visibilityState[column.accessorKey] =
column.defaultHidden === true ? false : true;
}
}
});
return visibilityState;
} catch (e) {
console.error("Error while loading saved column visibility", e);
return {};
}
},
);
useEffect(() => {
const localStorageItem = localStorage.getItem(localStorageKey);
if (!localStorageItem || localStorageItem === "{}") {
const initialVisibility: VisibilityState = {};
columns.forEach((column) => {
if ("accessorKey" in column && typeof column.accessorKey === "string") {
initialVisibility[column.accessorKey] =
column.defaultHidden === true ? false : true;
}
});
setColumnVisibility(initialVisibility);
} else {
// make sure all columns are in the visibility state
const visibilityState = JSON.parse(localStorageItem) as VisibilityState;
columns.forEach((column) => {
if ("accessorKey" in column && typeof column.accessorKey === "string") {
if (!(column.accessorKey in visibilityState)) {
visibilityState[column.accessorKey] =
column.defaultHidden === true ? false : true;
}
}
});
}
}, [columns, localStorageKey]);
useEffect(() => {
localStorage.setItem(localStorageKey, JSON.stringify(columnVisibility));
}, [columnVisibility, localStorageKey]);
return [columnVisibility, setColumnVisibility] as const;
}
export default useColumnVisibility;
@@ -1,18 +0,0 @@
import { type Key, type ReactNode } from "react";
import { cn } from "@/src/utils/tailwind";
export const RightAlignedCell = ({
children,
className,
key,
}: {
children: ReactNode;
className?: string;
key?: Key;
}) => {
return (
<div className={cn("text-right", className)} key={key}>
{children}
</div>
);
};
@@ -1,88 +0,0 @@
import {
dateTimeAggregationOptions,
dateTimeAggregationSettings,
} from "@/src/features/dashboard/lib/timeseries-aggregation";
import { z } from "zod";
import {
createTRPCRouter,
protectedProjectProcedure,
} from "@/src/server/api/trpc";
import { executeQuery } from "@/src/server/api/services/query-builder";
import { sqlInterface } from "@/src/server/api/services/sqlInterface";
export const dashboardRouter = createTRPCRouter({
chart: protectedProjectProcedure
.input(sqlInterface.extend({ projectId: z.string() }))
.query(async ({ input, ctx }) => {
return await executeQuery(ctx.prisma, input.projectId, input);
}),
scores: protectedProjectProcedure
.input(
z.object({
projectId: z.string(),
agg: z.enum(dateTimeAggregationOptions),
}),
)
.query(async ({ input, ctx }) => {
// queryRawUnsafe to add input.agg to the WHERE clause
const output = await ctx.prisma.$queryRawUnsafe<
{
date_trunc: Date;
values: {
[key: string]: number;
} | null;
}[]
>(`
WITH timeseries AS (
SELECT
date_trunc('${
dateTimeAggregationSettings[input.agg].date_trunc
}', dt) as date_trunc
FROM generate_series(
NOW() - INTERVAL '${input.agg}', NOW(), INTERVAL '1 minute'
) as dt
WHERE dt > NOW() - INTERVAL '${input.agg}'
GROUP BY 1
),
metrics AS (
SELECT
date_trunc('${
dateTimeAggregationSettings[input.agg].date_trunc
}', scores.timestamp) as date_trunc,
scores.name as metric_name,
AVG(value) as avg_value
FROM scores
LEFT JOIN traces ON scores.trace_id = traces.id
WHERE scores.timestamp > NOW() - INTERVAL '${input.agg}'
AND traces.project_id = '${input.projectId}'
GROUP BY 1,2
),
json_metrics AS (
SELECT
date_trunc,
jsonb_object_agg(metric_name, avg_value) as values
FROM metrics
GROUP BY 1
)
SELECT
timeseries.date_trunc,
json_metrics.values as values
FROM timeseries
LEFT JOIN json_metrics ON timeseries.date_trunc = json_metrics.date_trunc
ORDER BY 1
`);
return output.map((row) => ({
...row,
values: row.values
? Object.entries(row.values).map(([label, value]) => ({
label: "avg_" + label,
value,
}))
: [],
ts: row.date_trunc.getTime(),
}));
}),
});
-300
View File
@@ -1,300 +0,0 @@
import {
type TiktokenEncoding,
get_encoding,
encoding_for_model,
type TiktokenModel,
type Tiktoken,
} from "tiktoken";
import { countTokens } from "@anthropic-ai/tokenizer";
import { type PricingUnit, type Pricing } from "@prisma/client";
import { Decimal } from "decimal.js";
type ChatMessage = {
role: string;
name?: string;
content: string;
};
type TokenCalculationParams = {
messages: ChatMessage[];
model: TiktokenModel;
};
export function tokenCount(p: {
model: string;
text: unknown;
}): number | undefined {
if (
p.text === null ||
p.text === undefined ||
(Array.isArray(p.text) && p.text.length === 0)
) {
return undefined;
} else if (isOpenAiModel(p.model)) {
return isChatMessageArray(p.text)
? openAiChatTokenCount({
model: p.model,
messages: p.text,
})
: isString(p.text)
? openAiStringTokenCount({ model: p.model, text: p.text })
: openAiStringTokenCount({
model: p.model,
text: JSON.stringify(p.text),
});
} else if (isClaudeModel(p.model)) {
return isString(p.text)
? claudeStringTokenCount({ model: p.model, text: p.text })
: claudeStringTokenCount({
model: p.model,
text: JSON.stringify(p.text),
});
} else {
console.log("Unknown model provider", p.model);
return undefined;
}
}
function openAiChatTokenCount(params: TokenCalculationParams) {
let encoding: Tiktoken;
try {
encoding = encoding_for_model(params.model);
} catch (KeyError) {
console.log("Warning: model not found. Using cl100k_base encoding.");
encoding = get_encoding("cl100k_base");
}
let tokens_per_message = 0;
let tokens_per_name = 0;
if (
[
"gpt-3.5-turbo-0613",
"gpt-3.5-turbo-16k-0613",
"gpt-4-0314",
"gpt-4-32k-0314",
"gpt-4-0613",
"gpt-4-32k-0613",
].includes(params.model)
) {
tokens_per_message = 3;
tokens_per_name = 1;
} else if (params.model === "gpt-3.5-turbo-0301") {
tokens_per_message = 4; // every message follows <|start|>{role/name}\n{content}<|end|>\n
tokens_per_name = -1; // if there's a name, the role is omitted
} else if (
params.model.includes("gpt-3.5-turbo") ||
params.model.startsWith("gpt-3.5")
) {
return openAiChatTokenCount({ ...params, model: "gpt-3.5-turbo-0613" });
} else if (params.model.includes("gpt-4")) {
return openAiChatTokenCount({ ...params, model: "gpt-4-0613" });
} else {
console.error(`Not implemented for model ${params.model}`);
throw new Error(`Not implemented for model ${params.model}`);
}
let num_tokens = 0;
params.messages.forEach((message) => {
num_tokens += tokens_per_message;
Object.keys(message).forEach((key) => {
const value = message[key as keyof typeof message];
if (value) {
num_tokens += encoding.encode(value).length;
}
if (key === "name") {
num_tokens += tokens_per_name;
}
});
});
num_tokens += 3; // every reply is primed with <| start |> assistant <| message |>
return num_tokens;
}
const openAiStringTokenCount = (p: { model: string; text: string }) => {
if (
p.model.toLowerCase().startsWith("gpt") ||
p.model.toLowerCase().includes("ada")
) {
return getTokens("cl100k_base", p.text);
}
if (p.model.toLowerCase().startsWith("text-davinci")) {
return getTokens("p50k_base", p.text);
}
console.log("Unknown model", p.model);
return undefined;
};
const claudeStringTokenCount = (p: { model: string; text: string }) => {
return countTokens(p.text);
};
const getTokens = (name: TiktokenEncoding, text: string) => {
const encoding = get_encoding(name);
const tokens = encoding.encode(text);
encoding.free();
return tokens.length;
};
function isString(value: unknown): value is string {
return typeof value === "string";
}
function isClaudeModel(model: string) {
return model.toLowerCase().startsWith("claude");
}
function isOpenAiModel(model: string): model is TiktokenModel {
return (
[
"text-davinci-003",
"text-davinci-002",
"text-davinci-001",
"text-curie-001",
"text-babbage-001",
"text-ada-001",
"davinci",
"curie",
"babbage",
"ada",
"code-davinci-002",
"code-davinci-001",
"code-cushman-002",
"code-cushman-001",
"davinci-codex",
"cushman-codex",
"text-davinci-edit-001",
"code-davinci-edit-001",
"text-embedding-ada-002",
"text-similarity-davinci-001",
"text-similarity-curie-001",
"text-similarity-babbage-001",
"text-similarity-ada-001",
"text-search-davinci-doc-001",
"text-search-curie-doc-001",
"text-search-babbage-doc-001",
"text-search-ada-doc-001",
"code-search-babbage-code-001",
"code-search-ada-code-001",
"gpt2",
"gpt-4",
"gpt-4-0314",
"gpt-4-0613",
"gpt-4-32k",
"gpt-4-32k-0314",
"gpt-4-32k-0613",
"gpt-4-1106-preview",
"gpt-4-vision-preview",
"gpt-3.5",
"gpt-3.5-turbo",
"gpt-3.5-turbo-0301",
"gpt-3.5-turbo-0613",
"gpt-3.5-turbo-16k",
"gpt-3.5-turbo-16k-0613",
"gpt-3.5-turbo-1106",
].find((m) => m === model) !== undefined
);
}
function isChatMessageArray(value: unknown): value is ChatMessage[] {
if (!Array.isArray(value)) {
return false;
}
return value.every(
(item: unknown) =>
typeof item === "object" &&
item !== null &&
"role" in item &&
typeof item.role === "string" &&
"content" in item &&
typeof item.content === "string" &&
(!("name" in item) || typeof item.name === "string"),
);
}
export function calculateTokenCost(
pricingList: Pricing[],
input: {
model: string;
input: unknown;
output: unknown;
totalTokens: Decimal;
promptTokens: Decimal;
completionTokens: Decimal;
},
): Decimal | undefined {
const pricing = pricingList.filter((p) => p.modelName === input.model);
if (pricing.length === 0) {
console.log("no pricing found for model", input.model);
return undefined;
} else {
if (pricing.length === 1 && pricing[0]?.tokenType === "TOTAL") {
return calculateValue(
pricing[0].price,
pricing[0].pricingUnit,
input.totalTokens,
JSON.stringify(input.input) + JSON.stringify(input.output),
);
}
if (pricing.length === 2) {
let promptPrice: Decimal = new Decimal(0);
let completionPrice: Decimal = new Decimal(0);
const promptPricing = pricing.find((p) => p.tokenType === "PROMPT");
const completionPricing = pricing.find(
(p) => p.tokenType === "COMPLETION",
);
if (promptPricing) {
promptPrice =
calculateValue(
promptPricing.price,
promptPricing.pricingUnit,
input.promptTokens,
JSON.stringify(input.input),
) ?? new Decimal(0);
}
if (completionPricing) {
completionPrice =
calculateValue(
completionPricing.price,
completionPricing.pricingUnit,
input.completionTokens,
JSON.stringify(input.output),
) ?? new Decimal(0);
}
return promptPrice.plus(completionPrice);
}
console.log("unknown model", input.model);
return undefined;
}
}
const calculateValue = (
price: Decimal,
unit: PricingUnit,
tokens: Decimal,
characters: string,
) => {
switch (unit) {
case "PER_1000_TOKENS":
return price
.times(tokens.dividedBy(new Decimal(1000)))
.toDecimalPlaces(5);
case "PER_1000_CHARS":
return (
price
// strip whitespace, default for google bison, only character based model for now
.times(new Decimal(characters.replace(/\s/g, "").length))
.dividedBy(new Decimal(1000))
.toDecimalPlaces(5)
);
default:
console.log("unknown pricing unit", unit);
return undefined;
}
};
@@ -1,121 +0,0 @@
import Header from "@/src/components/layouts/header";
import { Badge } from "@/src/components/ui/badge";
import { Button } from "@/src/components/ui/button";
import { CodeView } from "@/src/components/ui/code";
import { DetailPageNav } from "@/src/features/navigate-detail-pages/DetailPageNav";
import { CreatePromptDialog } from "@/src/features/prompts/components/new-prompt-button";
import { useHasAccess } from "@/src/features/rbac/utils/checkAccess";
import { api } from "@/src/utils/api";
import { extractVariables } from "@/src/utils/string";
import { type Prompt } from "@prisma/client";
import { Pencil } from "lucide-react";
import router from "next/router";
export type PromptDetailProps = {
projectId: string;
promptId: string;
};
export const PromptDetail = (props: PromptDetailProps) => {
const prompt = api.prompts.byId.useQuery({
id: props.promptId,
projectId: props.projectId,
});
const extractedVariables = prompt.data
? extractVariables(prompt.data.prompt)
: [];
if (!prompt.data) {
return <div>Loading...</div>;
}
return (
<div className="flex flex-col overflow-hidden xl:container md:h-[calc(100vh-100px)] xl:h-[calc(100vh-40px)]">
<Header
title={`${prompt.data.name} (v${prompt.data.version})`}
status={prompt.data.isActive ? "production" : "disabled"}
breadcrumb={[
{
name: "Prompts",
href: `/project/${props.projectId}/prompts/`,
},
{ name: `${prompt.data.name} (v${prompt.data.version})` },
]}
actionButtons={
<>
<CreatePromptDialog
projectId={props.projectId}
title="Update Prompt"
subtitle="We do not update prompts, instead we create a new version of the prompt."
promptName={prompt.data.name}
promptText={prompt.data.prompt}
>
<Button variant="outline" size="icon">
<Pencil className="h-5 w-5" />
</Button>
</CreatePromptDialog>
<DetailPageNav
key="nav"
currentId={props.promptId}
path={(id) =>
`/project/${router.query.projectId as string}/prompts/${id}`
}
listKey="prompts"
/>
</>
}
/>
<CodeView content={prompt.data.prompt} title="Prompt" />
<div className="mx-auto mt-5 w-full rounded-lg border text-base leading-7 text-gray-700">
<div className="border-b px-3 py-1 text-xs font-medium">Variables</div>
<div className="flex flex-wrap gap-2 p-3">
{extractedVariables.length > 0 ? (
extractedVariables.map((variable) => (
<Badge key={variable} variant="outline">
{variable}
</Badge>
))
) : (
<span className="text-xs">No variables</span>
)}
</div>
</div>
</div>
);
};
export function UpdatePrompt({
projectId,
prompt,
isLoading,
}: {
projectId: string;
prompt: Prompt | undefined;
isLoading: boolean;
}) {
const hasAccess = useHasAccess({ projectId, scope: "prompts:CUD" });
const handlePromptEdit = () => {
void router.push(
`/project/${projectId}/prompts/${prompt?.id}/edit`,
undefined,
{
shallow: true,
},
);
};
return (
<Button
variant="outline"
size="icon"
onClick={() => handlePromptEdit()}
disabled={!hasAccess}
loading={isLoading}
>
<Pencil className="h-5 w-5" />
</Button>
);
}
@@ -1,203 +0,0 @@
import { z } from "zod";
import {
createTRPCRouter,
protectedProjectProcedure,
} from "@/src/server/api/trpc";
import { throwIfNoAccess } from "@/src/features/rbac/utils/checkAccess";
import { type PrismaClient } from "@prisma/client";
export const CreatePrompt = z.object({
projectId: z.string(),
name: z.string(),
isActive: z.boolean(),
prompt: z.string(),
});
export const promptRouter = createTRPCRouter({
all: protectedProjectProcedure
.input(
z.object({
projectId: z.string(),
}),
)
.query(async ({ input, ctx }) => {
throwIfNoAccess({
session: ctx.session,
projectId: input.projectId,
scope: "prompts:read",
});
return ctx.prisma.prompt.findMany({
where: {
projectId: input.projectId,
},
orderBy: [{ name: "asc" }, { version: "desc" }],
});
}),
byId: protectedProjectProcedure
.input(
z.object({
projectId: z.string(),
id: z.string(),
}),
)
.query(async ({ input, ctx }) => {
throwIfNoAccess({
session: ctx.session,
projectId: input.projectId,
scope: "prompts:read",
});
return ctx.prisma.prompt.findFirst({
where: {
id: input.id,
projectId: input.projectId,
},
});
}),
create: protectedProjectProcedure
.input(CreatePrompt)
.mutation(async ({ input, ctx }) => {
try {
throwIfNoAccess({
session: ctx.session,
projectId: input.projectId,
scope: "prompts:CUD",
});
return await createPrompt({
projectId: input.projectId,
name: input.name,
prompt: input.prompt,
isActive: input.isActive,
createdBy: ctx.session.user.id,
prisma: ctx.prisma,
});
} catch (e) {
console.log(e);
throw e;
}
}),
promote: protectedProjectProcedure
.input(z.object({ promptId: z.string(), projectId: z.string() }))
.mutation(async ({ input, ctx }) => {
try {
throwIfNoAccess({
session: ctx.session,
projectId: input.projectId,
scope: "prompts:CUD",
});
const toBePromotedPrompt = await ctx.prisma.prompt.findUniqueOrThrow({
where: {
id: input.promptId,
},
});
const latestActivePrompt = await ctx.prisma.prompt.findMany({
where: {
projectId: input.projectId,
name: toBePromotedPrompt.name,
isActive: true,
},
orderBy: [{ version: "desc" }],
take: 1,
});
if (latestActivePrompt.length > 1) {
throw new Error(
`Expected exactly zero or one active prompt of name '${toBePromotedPrompt.name}', got ${latestActivePrompt.length}`,
);
}
const toBeExecuted = [
ctx.prisma.prompt.update({
where: {
id: toBePromotedPrompt.id,
},
data: {
isActive: true,
},
}),
];
if (latestActivePrompt.length === 1)
toBeExecuted.push(
ctx.prisma.prompt.update({
where: {
id: latestActivePrompt[0]?.id,
},
data: {
isActive: false,
},
}),
);
await ctx.prisma.$transaction(toBeExecuted);
} catch (e) {
console.log(e);
throw e;
}
}),
});
export const createPrompt = async ({
projectId,
name,
prompt,
isActive = true,
createdBy,
prisma,
}: {
projectId: string;
name: string;
prompt: string;
isActive?: boolean;
createdBy: string;
prisma: PrismaClient;
}) => {
const latestPrompt = await prisma.prompt.findFirst({
where: {
projectId: projectId,
name: name,
},
orderBy: [{ version: "desc" }],
take: 1,
});
const latestActivePrompt = await prisma.prompt.findFirst({
where: {
projectId: projectId,
name: name,
isActive: true,
},
orderBy: [{ version: "desc" }],
take: 1,
});
const create = [
prisma.prompt.create({
data: {
prompt: prompt,
name: name,
version: latestPrompt?.version ? latestPrompt.version + 1 : 1,
isActive: isActive,
project: { connect: { id: projectId } },
createdBy: createdBy,
},
}),
];
if (latestActivePrompt && isActive)
// If we're creating a new active prompt, we need to deactivate the old one
create.push(
prisma.prompt.update({
where: {
id: latestActivePrompt.id,
},
data: {
isActive: false,
},
}),
);
const [createdPrompt] = await prisma.$transaction(create);
return createdPrompt;
};
-133
View File
@@ -1,133 +0,0 @@
import { env } from "@/src/env.mjs";
import {
createShaHash,
verifySecretKey,
} from "@/src/features/public-api/lib/apiKeys";
import { type ApiAccessScope } from "@/src/features/public-api/server/types";
import { prisma } from "@/src/server/db";
import { instrumentAsync } from "@/src/utils/instrumentation";
export type AuthHeaderVerificationResult =
| {
validKey: true;
scope: ApiAccessScope;
}
| {
validKey: false;
error: string;
};
export async function verifyAuthHeaderAndReturnScope(
authHeader: string | undefined,
): Promise<AuthHeaderVerificationResult> {
return instrumentAsync(
{ name: "verifyAuthHeaderAndReturnScope" },
async () => {
if (!authHeader) {
console.error("No authorization header");
return {
validKey: false,
error: "No authorization header",
};
}
try {
// Basic auth, full scope, needs secret key and public key
if (authHeader.startsWith("Basic ")) {
const { username: publicKey, password: secretKey } =
extractBasicAuthCredentials(authHeader);
const salt = env.SALT;
const hashFromProvidedKey = createShaHash(secretKey, salt);
const apiKey = await prisma.apiKey.findUnique({
where: { fastHashedSecretKey: hashFromProvidedKey },
});
let projectId = apiKey?.projectId;
if (!apiKey || !apiKey.fastHashedSecretKey) {
const dbKey = await findDbKeyOrThrow(publicKey);
const isValid = await verifySecretKey(
secretKey,
dbKey.hashedSecretKey,
);
if (!isValid) {
console.log("Old key is invalid", publicKey);
throw new Error("Invalid credentials");
}
const shaKey = createShaHash(secretKey, salt);
await prisma.apiKey.update({
where: { publicKey },
data: {
fastHashedSecretKey: shaKey,
},
});
projectId = dbKey.projectId;
}
if (!projectId) {
console.log("No project id found for key", publicKey);
throw new Error("Invalid credentials");
}
return {
validKey: true,
scope: {
projectId: projectId,
accessLevel: "all",
},
};
}
// Bearer auth, limited scope, only needs public key
if (authHeader.startsWith("Bearer ")) {
const publicKey = authHeader.replace("Bearer ", "");
const dbKey = await findDbKeyOrThrow(publicKey);
return {
validKey: true,
scope: {
projectId: dbKey.projectId,
accessLevel: "scores",
},
};
}
} catch (error: unknown) {
console.error("Error verifying auth header: ", error);
return {
validKey: false,
error: error instanceof Error ? error.message : "Authorization error",
};
}
return {
validKey: false,
error: "Invalid authorization header",
};
},
);
}
function extractBasicAuthCredentials(basicAuthHeader: string): {
username: string;
password: string;
} {
const authValue = basicAuthHeader.split(" ")[1];
if (!authValue) throw new Error("Invalid authorization header");
const [username, password] = atob(authValue).split(":");
if (!username || !password) throw new Error("Invalid authorization header");
return { username, password };
}
async function findDbKeyOrThrow(publicKey: string) {
const dbKey = await prisma.apiKey.findUnique({
where: { publicKey },
});
if (!dbKey) {
console.log("No api key found for public key:", publicKey);
throw new Error("Invalid public key");
}
return dbKey;
}
@@ -1,93 +0,0 @@
// Langfuse Cloud only
import { Button } from "@/src/components/ui/button";
import { env } from "@/src/env.mjs";
import { api } from "@/src/utils/api";
import { Card, Flex, MarkerBar, Metric, Text } from "@tremor/react";
import {
chatAvailable,
sendUserChatMessage,
showAgentChatMessage,
} from "@/src/features/support-chat/chat";
import Link from "next/link";
export const ProjectUsageChart: React.FC<{ projectId: string }> = ({
projectId,
}) => {
const usage = api.usageMetering.currentMonth.useQuery({
projectId,
});
const project = api.projects.byId.useQuery({ projectId });
const planLimit =
project.data?.cloudConfig?.monthlyObservationLimit ?? 100_000;
const plan = project.data?.cloudConfig?.plan ?? "Hobby";
const currentMonth = new Date().toLocaleDateString("en-US", {
month: "short",
});
if (!env.NEXT_PUBLIC_LANGFUSE_CLOUD_REGION) return null;
return (
<div>
<h2 className="mb-5 text-base font-semibold leading-6 text-gray-900">
Usage
</h2>
<Card className="p-4 lg:w-1/2">
{usage.data !== undefined ? (
<>
<Text>Observations / month</Text>
<Metric>{usage.data}</Metric>
<Flex className="mt-4">
<Text>
{`${currentMonth}: ${usage.data} (${(
(usage.data / planLimit) *
100
).toLocaleString(undefined, {
maximumFractionDigits: 2,
})}%)`}
</Text>
<Text>Plan limit: {simplifyNumber(planLimit)}</Text>
</Flex>
<MarkerBar
value={Math.min((usage.data / planLimit) * 100, 100)}
className="mt-3"
/>
</>
) : null}
</Card>
<div className="mt-4 flex flex-row items-center gap-2">
{chatAvailable && (
<Button
variant="secondary"
className=""
onClick={() => {
sendUserChatMessage(
"I want to change my plan, project: " + projectId,
);
// wait for 2 seconds
setTimeout(() => {
showAgentChatMessage(
"We're happy to help. Which plan would you like to change to? See https://langfuse.com/#pricing for details on available plans.",
);
}, 2000);
}}
>
Request plan change
</Button>
)}
<Button variant="secondary" asChild>
<Link href="https://langfuse.com/pricing">View plans</Link>
</Button>
<div className="inline-block text-sm text-gray-500">
Currently: {plan}
</div>
</div>
</div>
);
};
function simplifyNumber(num: number) {
if (num >= 1000000) return num / 1000000 + "m";
if (num >= 1000) return num / 1000 + "k";
return num.toString();
}
-35
View File
@@ -1,35 +0,0 @@
// Middleware to block requests from certain IPs on Langfuse Cloud
// Not included in the self-host build, removed in Dockerfile
// import { type NextApiRequest } from "next";
// import { type NextRequest } from "next/server";
// import { get } from "@vercel/edge-config";
// export async function middleware(req: NextRequest) {
// try {
// if (process.env.NEXT_PUBLIC_LANGFUSE_CLOUD_REGION !== undefined) {
// const config = await get("blockedIps");
// const blockedIps = Array.isArray(config) ? config : [config];
// const ip = getIP(req);
// if (ip && blockedIps.includes(ip)) {
// console.log("Blocked request by ip: ", ip);
// return new Response("Access denied", { status: 403 });
// }
// }
// return;
// } catch (e) {
// console.error("Server side error in middleware: ", e);
// return new Response("Internal server error", { status: 500 });
// }
// }
// export default function getIP(request: Request | NextApiRequest) {
// const xff =
// request instanceof Request
// ? request.headers.get("x-forwarded-for")
// : request.headers["x-forwarded-for"];
// return xff ? (Array.isArray(xff) ? xff[0] : xff.split(",")[0]) : "127.0.0.1";
// }
-206
View File
@@ -1,206 +0,0 @@
import { type NextApiRequest, type NextApiResponse } from "next";
import { z } from "zod";
import { cors, runMiddleware } from "@/src/features/public-api/server/cors";
import { prisma } from "@/src/server/db";
import { verifyAuthHeaderAndReturnScope } from "@/src/features/public-api/server/apiAuth";
import { Prisma } from "@prisma/client";
import { paginationZod } from "@/src/utils/zod";
const GetUsageSchema = z.object({
...paginationZod,
group_by: z.enum(["trace_name"]).nullish(),
trace_name: z.string().nullish(),
});
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
try {
if (req.method === "GET") {
if (authCheck.scope.accessLevel !== "all") {
return res.status(401).json({
message:
"Access denied - need to use basic auth with secret key to GET scores",
});
}
const obj = GetUsageSchema.parse(req.query); // uses query and not body
const traceNameCondition = obj.trace_name
? Prisma.sql`AND t.name = ${obj.trace_name}`
: Prisma.empty;
if (obj.group_by === undefined) {
const usage = await prisma.$queryRaw`
WITH model_usage AS (
SELECT
DATE_TRUNC('DAY',
o.start_time) observation_day,
o.model,
SUM(o.prompt_tokens) prompt_tokens,
SUM(o.completion_tokens) completion_tokens,
SUM(o.total_tokens) total_tokens
FROM
traces t
LEFT JOIN observations o ON o.trace_id = t.id
WHERE o.start_time IS NOT NULL
AND o.project_id = ${authCheck.scope.projectId}
AND t.project_id = ${authCheck.scope.projectId}
${traceNameCondition}
GROUP BY 1,2
order by 1,2
),
daily_usage AS (
SELECT
observation_day,
json_agg(json_build_object('model',
model,
'prompt_tokens',
prompt_tokens,
'completion_tokens',
completion_tokens,
'total_tokens',
total_tokens)) daily_usage_json
FROM model_usage
group by 1
)
SELECT
observation_day "date",
daily_usage_json usage
FROM daily_usage
ORDER BY 1 desc
LIMIT ${obj.limit} OFFSET ${(obj.page - 1) * obj.limit}
`;
const totalItemsRes = await prisma.$queryRaw<{ count: bigint }[]>`
SELECT
count(DISTINCT DATE_TRUNC('DAY', observations.start_time))
FROM
observations
JOIN traces ON observations.trace_id = traces.id
WHERE traces.project_id = ${authCheck.scope.projectId}
`;
const totalItems =
totalItemsRes[0] !== undefined ? Number(totalItemsRes[0].count) : 0;
return res.status(200).json({
data: usage,
meta: {
page: obj.page,
limit: obj.limit,
totalItems,
totalPages: Math.ceil(totalItems / obj.limit),
},
});
} else if (obj.group_by === "trace_name") {
const usage = await prisma.$queryRaw`
WITH model_usage AS (
SELECT
t."name" trace_name,
DATE_TRUNC('DAY',
o.start_time) observation_day,
o.model,
SUM(o.prompt_tokens) prompt_tokens,
SUM(o.completion_tokens) completion_tokens,
SUM(o.total_tokens) total_tokens
FROM
traces t
LEFT JOIN observations o ON o.trace_id = t.id
WHERE o.start_time IS NOT NULL
AND t.project_id = ${authCheck.scope.projectId}
AND o.project_id = ${authCheck.scope.projectId}
${traceNameCondition}
GROUP BY 1,2,3
order by 1,2,3
),
daily_usage AS (
SELECT
trace_name,
observation_day,
json_agg(json_build_object('model',
model,
'prompt_tokens',
prompt_tokens,
'completion_tokens',
completion_tokens,
'total_tokens',
total_tokens)) daily_usage_json
FROM model_usage
WHERE prompt_tokens > 0
OR completion_tokens > 0
OR total_tokens > 0
group by 1,2
order by 1,2 desc
),
all_trace_names AS (
SELECT t."name" trace_name
FROM traces t
WHERE t.project_id = ${authCheck.scope.projectId}
${traceNameCondition}
GROUP BY 1
)
SELECT
all_trace_names.trace_name,
json_agg(json_build_object(
'date',
observation_day,
'usage',
daily_usage_json
)) metrics
FROM all_trace_names
LEFT JOIN daily_usage ON all_trace_names.trace_name = daily_usage.trace_name
group by 1
ORDER BY 1
LIMIT ${obj.limit} OFFSET ${(obj.page - 1) * obj.limit}
`;
const totalItemsRes = await prisma.$queryRaw<{ count: bigint }[]>`
SELECT
count(DISTINCT CASE WHEN "name" IS NULL THEN 'COUNT_NULL' ELSE "name" END)
FROM
traces
WHERE project_id = ${authCheck.scope.projectId}
`;
const totalItems =
totalItemsRes[0] !== undefined ? Number(totalItemsRes[0].count) : 0;
return res.status(200).json({
data: usage,
meta: {
page: obj.page,
limit: obj.limit,
totalItems,
totalPages: Math.ceil(totalItems / obj.limit),
},
});
} else {
return res.status(400).json({
message: "Invalid group_by value",
});
}
} else {
console.error(req.method, req.body);
return res.status(405).json({ message: "Method not allowed" });
}
} 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,
});
}
}
-423
View File
@@ -1,423 +0,0 @@
import { z } from "zod";
import {
createTRPCRouter,
protectedProjectProcedure,
} from "@/src/server/api/trpc";
import { type Observation, Prisma } from "@prisma/client";
import { paginationZod } from "@/src/utils/zod";
import { singleFilter } from "@/src/server/api/interfaces/filters";
import {
datetimeFilterToPrismaSql,
filterToPrismaSql,
} from "@/src/features/filters/server/filterToPrisma";
import {
type ObservationOptions,
observationsTableCols,
} from "@/src/server/api/definitions/observationsTable";
import { calculateTokenCost } from "@/src/features/ingest/lib/usage";
import Decimal from "decimal.js";
import { usdFormatter } from "@/src/utils/numbers";
import { env } from "@/src/env.mjs";
import {
S3Client,
PutObjectCommand,
GetObjectCommand,
} from "@aws-sdk/client-s3";
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
import {
exportFileFormats,
exportOptions,
} from "@/src/server/api/interfaces/exportTypes";
const GenerationFilterOptions = z.object({
projectId: z.string(), // Required for protectedProjectProcedure
filter: z.array(singleFilter),
searchQuery: z.string().nullable(),
});
const ListInputs = GenerationFilterOptions.extend({
...paginationZod,
});
// extend generationfilteroptions with export options
const ExportInputs = GenerationFilterOptions.extend({
fileFormat: z.enum(exportFileFormats),
});
export const generationsRouter = createTRPCRouter({
all: protectedProjectProcedure
.input(ListInputs)
.query(async ({ input, ctx }) => {
const searchCondition = input.searchQuery
? Prisma.sql`AND (
o."id" ILIKE ${`%${input.searchQuery}%`} OR
o."name" ILIKE ${`%${input.searchQuery}%`} OR
o."model" ILIKE ${`%${input.searchQuery}%`} OR
t."name" ILIKE ${`%${input.searchQuery}%`}
)`
: Prisma.empty;
const filterCondition = filterToPrismaSql(
input.filter,
observationsTableCols,
);
// to improve query performance, add timeseries filter to observation queries as well
const startTimeFilter = input.filter.find(
(f) => f.column === "start_time" && f.type === "datetime",
);
const datetimeFilter =
startTimeFilter && startTimeFilter.type === "datetime"
? datetimeFilterToPrismaSql(
"start_time",
startTimeFilter.operator,
startTimeFilter.value,
)
: Prisma.empty;
const generations = await ctx.prisma.$queryRaw<
Array<
Observation & {
traceId: string;
traceName: string;
totalCount: number;
latency: number | null;
}
>
>(
Prisma.sql`
WITH observations_with_latency AS (
SELECT
o.*,
CASE WHEN o.end_time IS NULL THEN NULL ELSE (EXTRACT(EPOCH FROM o."end_time") - EXTRACT(EPOCH FROM o."start_time"))::double precision END AS "latency"
FROM observations o
WHERE o.type = 'GENERATION'
AND o.project_id = ${input.projectId}
${datetimeFilter}
)
SELECT
o.id,
o.name,
o.model,
o.start_time as "startTime",
o.end_time as "endTime",
o.latency,
o.input,
o.output,
o.metadata,
o.trace_id as "traceId",
t.name as "traceName",
o.completion_start_time as "completionStartTime",
o.prompt_tokens as "promptTokens",
o.completion_tokens as "completionTokens",
o.total_tokens as "totalTokens",
o.level,
o.status_message as "statusMessage",
o.version,
(count(*) OVER())::int AS "totalCount"
FROM observations_with_latency o
JOIN traces t ON t.id = o.trace_id
WHERE
t.project_id = ${input.projectId}
${searchCondition}
${filterCondition}
ORDER BY o.start_time DESC
LIMIT ${input.limit}
OFFSET ${input.page * input.limit}
`,
);
const pricings = await ctx.prisma.pricing.findMany();
return generations.map(({ input, output, ...rest }) => {
return {
...rest,
input,
output,
cost: rest.model
? calculateTokenCost(pricings, {
model: rest.model,
totalTokens: new Decimal(rest.totalTokens),
promptTokens: new Decimal(rest.promptTokens),
completionTokens: new Decimal(rest.completionTokens),
input: input,
output: output,
})
: undefined,
};
});
}),
export: protectedProjectProcedure
.input(ExportInputs)
.query(async ({ input, ctx }) => {
const searchCondition = input.searchQuery
? Prisma.sql`AND (
o."id" ILIKE ${`%${input.searchQuery}%`} OR
o."name" ILIKE ${`%${input.searchQuery}%`} OR
o."model" ILIKE ${`%${input.searchQuery}%`} OR
t."name" ILIKE ${`%${input.searchQuery}%`}
)`
: Prisma.empty;
const filterCondition = filterToPrismaSql(
input.filter,
observationsTableCols,
);
console.log("filters: ", filterCondition);
const generations = await ctx.prisma.$queryRaw<
Array<
Observation & {
traceId: string;
traceName: string;
}
>
>(
Prisma.sql`
SELECT
o.id,
o.name,
o.model,
o.start_time as "startTime",
o.end_time as "endTime",
o.input,
o.output,
o.metadata,
o.trace_id as "traceId",
t.name as "traceName",
o.completion_start_time as "completionStartTime",
o.prompt_tokens as "promptTokens",
o.completion_tokens as "completionTokens",
o.total_tokens as "totalTokens",
o.version
FROM observations o
JOIN traces t ON t.id = o.trace_id
WHERE o.type = 'GENERATION'
AND o.project_id = ${input.projectId}
AND t.project_id = ${input.projectId}
${searchCondition}
${filterCondition}
ORDER BY o.start_time DESC
`,
);
const pricings = await ctx.prisma.pricing.findMany();
const enrichedGenerations = generations.map(
({ input, output, ...rest }) => {
return {
...rest,
input,
output,
cost: rest.model
? calculateTokenCost(pricings, {
model: rest.model,
totalTokens: new Decimal(rest.totalTokens),
promptTokens: new Decimal(rest.promptTokens),
completionTokens: new Decimal(rest.completionTokens),
input: input,
output: output,
})
: undefined,
};
},
);
let output: string = "";
// create file
switch (input.fileFormat) {
case "CSV":
output = [
[
"traceId",
"name",
"model",
"startTime",
"endTime",
"cost",
"prompt",
"completion",
"metadata",
],
]
.concat(
enrichedGenerations.map((generation) =>
[
generation.traceId,
generation.name ?? "",
generation.model ?? "",
generation.startTime.toISOString(),
generation.endTime?.toISOString() ?? "",
generation.cost
? usdFormatter(generation.cost.toNumber())
: "",
JSON.stringify(generation.input),
JSON.stringify(generation.output),
JSON.stringify(generation.metadata),
].map((field) => {
const str = typeof field === "string" ? field : String(field);
return `"${str.replace(/"/g, '""')}"`;
}),
),
)
.map((row) => row.join(","))
.join("\n");
break;
case "JSON":
output = JSON.stringify(enrichedGenerations);
break;
case "OPENAI-JSONL":
const inputSchemaOpenAI = z.array(
z.object({
role: z.enum(["system", "user", "assistant"]),
content: z.string(),
}),
);
const outputSchema = z.object({
completion: z.string(),
});
output = enrichedGenerations
.map((generation) => ({
parsedInput: inputSchemaOpenAI.safeParse(generation.input),
parsedOutput: outputSchema.safeParse(generation.output),
}))
.filter((generation) => generation.parsedInput.success)
.map((generation) =>
generation.parsedInput.success // check for typescript validation, is always true due to previous filter
? generation.parsedInput.data.concat(
generation.parsedOutput.success
? [
{
role: "assistant",
content: generation.parsedOutput.data.completion,
},
]
: [],
)
: [],
)
// to jsonl
.map((row) => JSON.stringify(row))
.join("\n");
break;
default:
throw new Error("Invalid export file format");
}
const fileName = `lf-export-${
input.projectId
}-${new Date().toISOString()}.${
exportOptions[input.fileFormat].extension
}`;
if (
env.S3_BUCKET_NAME &&
env.S3_ACCESS_KEY_ID &&
env.S3_SECRET_ACCESS_KEY &&
env.S3_ENDPOINT &&
env.S3_REGION
) {
const client = new S3Client({
credentials: {
accessKeyId: env.S3_ACCESS_KEY_ID,
secretAccessKey: env.S3_SECRET_ACCESS_KEY,
},
endpoint: env.S3_ENDPOINT,
region: env.S3_REGION,
});
await client.send(
new PutObjectCommand({
Bucket: env.S3_BUCKET_NAME,
Key: fileName,
Body: output,
ContentType: exportOptions[input.fileFormat].fileType,
Expires: new Date(Date.now() + 60 * 60 * 1000), // in 1 hour, file will be deleted
}),
);
const signedUrl = await getSignedUrl(
client,
new GetObjectCommand({
Bucket: env.S3_BUCKET_NAME,
Key: fileName,
ResponseContentDisposition: `attachment; filename="${fileName}"`,
}),
{
expiresIn: 60 * 60, // in 1 hour, signed url will expire
},
);
return {
type: "s3",
url: signedUrl,
fileName,
} as const;
} else {
return {
type: "data",
data: output,
fileName,
} as const;
}
}),
filterOptions: protectedProjectProcedure
.input(z.object({ projectId: z.string() }))
.query(async ({ input, ctx }) => {
const queryFilter = {
projectId: input.projectId,
type: "GENERATION",
} as const;
const model = await ctx.prisma.observation.groupBy({
by: ["model"],
where: queryFilter,
_count: { _all: true },
});
const name = await ctx.prisma.observation.groupBy({
by: ["name"],
where: queryFilter,
_count: { _all: true },
});
const traceName = await ctx.prisma.$queryRaw<
Array<{
traceName: string | null;
count: number;
}>
>(Prisma.sql`
SELECT
t.name "traceName",
count(*)::int AS count
FROM traces t
JOIN observations o ON o.trace_id = t.id
WHERE o.type = 'GENERATION'
AND o.project_id = ${input.projectId}
AND t.project_id = ${input.projectId}
GROUP BY 1
`);
// typecheck filter options, needs to include all columns with options
const res: ObservationOptions = {
model: model
.filter((i) => i.model !== null)
.map((i) => ({
value: i.model as string,
count: i._count._all,
})),
name: name
.filter((i) => i.name !== null)
.map((i) => ({
value: i.name as string,
count: i._count._all,
})),
traceName: traceName
.filter((i) => i.traceName !== null)
.map((i) => ({
value: i.traceName as string,
count: i.count,
})),
};
return res;
}),
});
-422
View File
@@ -1,422 +0,0 @@
import { tokenCount } from "@/src/features/ingest/lib/usage";
import { checkApiAccessScope } from "@/src/features/public-api/server/apiScope";
import { type ApiAccessScope } from "@/src/features/public-api/server/types";
import { AuthenticationError } from "@/src/pages/api/public/ingestion";
import {
type legacyObservationCreateEvent,
eventTypes,
type traceEvent,
type scoreEvent,
type eventCreateEvent,
type spanCreateEvent,
type generationCreateEvent,
type spanUpdateEvent,
type generationUpdateEvent,
type legacyObservationUpdateEvent,
type sdkLogEvent,
} from "@/src/features/public-api/server/ingestion-api-schema";
import { prisma } from "@/src/server/db";
import { ResourceNotFoundError } from "@/src/utils/exceptions";
import { mergeJson } from "@/src/utils/json";
import {
type Trace,
type Observation,
type Score,
type Prisma,
} from "@prisma/client";
import { v4 } from "uuid";
import { type z } from "zod";
import { jsonSchema } from "@/src/utils/zod";
export interface EventProcessor {
process(
apiScope: ApiAccessScope,
): Promise<Trace | Observation | Score> | undefined;
}
export class ObservationProcessor implements EventProcessor {
event:
| z.infer<typeof legacyObservationCreateEvent>
| z.infer<typeof legacyObservationUpdateEvent>
| z.infer<typeof eventCreateEvent>
| z.infer<typeof spanCreateEvent>
| z.infer<typeof spanUpdateEvent>
| z.infer<typeof generationCreateEvent>
| z.infer<typeof generationUpdateEvent>;
constructor(
event:
| z.infer<typeof legacyObservationCreateEvent>
| z.infer<typeof legacyObservationUpdateEvent>
| z.infer<typeof eventCreateEvent>
| z.infer<typeof spanCreateEvent>
| z.infer<typeof spanUpdateEvent>
| z.infer<typeof generationCreateEvent>
| z.infer<typeof generationUpdateEvent>,
) {
this.event = event;
}
async convertToObservation(apiScope: ApiAccessScope): Promise<{
id: string;
create: Prisma.ObservationCreateInput;
update: Prisma.ObservationUpdateInput;
}> {
const { body } = this.event;
let type;
switch (this.event.type) {
case eventTypes.OBSERVATION_CREATE:
case eventTypes.OBSERVATION_UPDATE:
type = this.event.body.type;
break;
case eventTypes.EVENT_CREATE:
type = "EVENT" as const;
break;
case eventTypes.SPAN_CREATE:
case eventTypes.SPAN_UPDATE:
type = "SPAN" as const;
break;
case eventTypes.GENERATION_CREATE:
case eventTypes.GENERATION_UPDATE:
type = "GENERATION" as const;
break;
}
const { id, traceId, name, startTime, metadata } = body;
const existingObservation = id
? await prisma.observation.findUnique({
where: { id, projectId: apiScope.projectId },
})
: null;
if (
this.event.type === eventTypes.OBSERVATION_UPDATE &&
!existingObservation
) {
throw new ResourceNotFoundError(this.event.id, "Observation not found");
}
const finalTraceId =
!traceId && !existingObservation
? // Create trace if no traceid
(
await prisma.trace.create({
data: {
projectId: apiScope.projectId,
name: name,
},
})
).id
: traceId;
const [newInputCount, newOutputCount] =
"usage" in body
? this.calculateTokenCounts(body, existingObservation ?? undefined)
: [undefined, undefined];
// merge metadata from existingObservation.metadata and metadata
const mergedMetadata = mergeJson(
existingObservation?.metadata
? jsonSchema.parse(existingObservation.metadata)
: undefined,
metadata ?? undefined,
);
const prompts =
"promptName" in this.event.body &&
typeof this.event.body.promptName === "string" &&
"promptVersion" in this.event.body &&
typeof this.event.body.promptVersion === "number"
? await prisma.prompt.findMany({
where: {
projectId: apiScope.projectId,
name: this.event.body.promptName,
version: this.event.body.promptVersion,
},
})
: undefined;
const observationId = id ?? v4();
return {
id: observationId,
create: {
id: observationId,
traceId: finalTraceId,
type: type,
name: name,
startTime: startTime ? new Date(startTime) : undefined,
endTime:
"endTime" in body && body.endTime
? new Date(body.endTime)
: undefined,
completionStartTime:
"completionStartTime" in body && body.completionStartTime
? new Date(body.completionStartTime)
: undefined,
metadata: mergedMetadata ?? metadata ?? undefined,
model: "model" in body ? body.model : undefined,
modelParameters:
"modelParameters" in body
? body.modelParameters ?? undefined
: undefined,
input: body.input ?? undefined,
output: body.output ?? undefined,
promptTokens: newInputCount,
completionTokens: newOutputCount,
totalTokens:
"usage" in body
? body.usage?.total ?? (newInputCount ?? 0) + (newOutputCount ?? 0)
: undefined,
unit: "usage" in body ? body.usage?.unit ?? undefined : undefined,
level: body.level ?? undefined,
statusMessage: body.statusMessage ?? undefined,
parentObservationId: body.parentObservationId ?? undefined,
version: body.version ?? undefined,
project: { connect: { id: apiScope.projectId } },
...(prompts && prompts.length === 1
? { prompt: { connect: { id: prompts[0]?.id } } }
: undefined),
},
update: {
name,
startTime: startTime ? new Date(startTime) : undefined,
endTime:
"endTime" in body && body.endTime
? new Date(body.endTime)
: undefined,
completionStartTime:
"completionStartTime" in body && body.completionStartTime
? new Date(body.completionStartTime)
: undefined,
metadata: mergedMetadata ?? metadata ?? undefined,
model: "model" in body ? body.model : undefined,
modelParameters:
"modelParameters" in body
? body.modelParameters ?? undefined
: undefined,
input: body.input ?? undefined,
output: body.output ?? undefined,
promptTokens: newInputCount,
completionTokens: newOutputCount,
totalTokens:
"usage" in body
? body.usage?.total ?? (newInputCount ?? 0) + (newOutputCount ?? 0)
: undefined,
unit: "usage" in body ? body.usage?.unit ?? undefined : undefined,
level: body.level ?? undefined,
statusMessage: body.statusMessage ?? undefined,
parentObservationId: body.parentObservationId ?? undefined,
version: body.version ?? undefined,
...(prompts && prompts.length === 1
? { prompt: { connect: { id: prompts[0]?.id } } }
: undefined),
},
};
}
calculateTokenCounts(
body:
| z.infer<typeof legacyObservationCreateEvent>["body"]
| z.infer<typeof generationCreateEvent>["body"],
existingObservation?: Observation,
) {
const mergedModel = body.model ?? existingObservation?.model;
const newPromptTokens =
body.usage?.input ??
((body.input || existingObservation?.input) && mergedModel
? tokenCount({
model: mergedModel,
text: body.input ?? existingObservation?.input,
})
: undefined);
const newCompletionTokens =
body.usage?.output ??
((body.output || existingObservation?.output) && mergedModel
? tokenCount({
model: mergedModel,
text: body.output ?? existingObservation?.output,
})
: undefined);
return [newPromptTokens, newCompletionTokens];
}
async process(
apiScope: ApiAccessScope,
): Promise<Trace | Observation | Score> {
if (apiScope.accessLevel !== "all")
throw new AuthenticationError("Access denied for observation creation");
const obs = await this.convertToObservation(apiScope);
return await prisma.observation.upsert({
where: {
id_projectId: {
id: obs.id,
projectId: apiScope.projectId,
},
},
create: obs.create,
update: obs.update,
});
}
}
export class TraceProcessor implements EventProcessor {
event: z.infer<typeof traceEvent>;
constructor(event: z.infer<typeof traceEvent>) {
this.event = event;
}
async process(
apiScope: ApiAccessScope,
): Promise<Trace | Observation | Score> {
const { body } = this.event;
if (apiScope.accessLevel !== "all")
throw new AuthenticationError("Access denied for trace creation");
const internalId = body.id ?? v4();
console.log(
"Trying to create trace, project ",
apiScope.projectId,
", body:",
body,
);
const existingTrace = await prisma.trace.findUnique({
where: {
id: internalId,
},
});
const mergedMetadata = mergeJson(
existingTrace?.metadata
? jsonSchema.parse(existingTrace.metadata)
: undefined,
body.metadata ?? undefined,
);
const upsertedTrace = await prisma.trace.upsert({
where: {
id: internalId,
projectId: apiScope.projectId,
},
create: {
id: internalId,
name: body.name ?? undefined,
userId: body.userId ?? undefined,
input: body.input ?? undefined,
output: body.output ?? undefined,
metadata: mergedMetadata ?? body.metadata ?? undefined,
release: body.release ?? undefined,
version: body.version ?? undefined,
session: body.sessionId
? {
connectOrCreate: {
where: { id: body.sessionId, projectId: apiScope.projectId },
create: { id: body.sessionId, projectId: apiScope.projectId },
},
}
: undefined,
public: body.public ?? undefined,
project: { connect: { id: apiScope.projectId } },
tags: body.tags ?? undefined,
},
update: {
name: body.name ?? undefined,
userId: body.userId ?? undefined,
input: body.input ?? undefined,
output: body.output ?? undefined,
metadata: mergedMetadata ?? body.metadata ?? undefined,
release: body.release ?? undefined,
version: body.version ?? undefined,
session: body.sessionId
? {
connectOrCreate: {
where: { id: body.sessionId, projectId: apiScope.projectId },
create: { id: body.sessionId, projectId: apiScope.projectId },
},
}
: undefined,
public: body.public ?? undefined,
tags: body.tags ?? undefined,
},
});
return upsertedTrace;
}
}
export class ScoreProcessor implements EventProcessor {
event: z.infer<typeof scoreEvent>;
constructor(event: z.infer<typeof scoreEvent>) {
this.event = event;
}
async process(
apiScope: ApiAccessScope,
): Promise<Trace | Observation | Score> {
const { body } = this.event;
const accessCheck = await checkApiAccessScope(
apiScope,
[
{ type: "trace", id: body.traceId },
...(body.observationId
? [{ type: "observation" as const, id: body.observationId }]
: []),
],
"score",
);
if (!accessCheck)
throw new AuthenticationError("Access denied for score creation");
const id = body.id ?? v4();
// access control via traceId
return await prisma.score.upsert({
where: {
id_traceId: {
id,
traceId: body.traceId,
},
},
create: {
id,
trace: { connect: { id: body.traceId } },
timestamp: new Date(),
value: body.value,
name: body.name,
comment: body.comment,
...(body.observationId && {
observation: { connect: { id: body.observationId } },
}),
},
update: {
timestamp: new Date(),
value: body.value,
name: body.name,
comment: body.comment,
...(body.observationId && {
observation: { connect: { id: body.observationId } },
}),
},
});
}
}
export class SdkLogProcessor implements EventProcessor {
event: z.infer<typeof sdkLogEvent>;
constructor(event: z.infer<typeof sdkLogEvent>) {
this.event = event;
}
process() {
return undefined;
}
}
-16
View File
@@ -1,16 +0,0 @@
import { PrismaClient } from "@prisma/client";
import { env } from "@/src/env.mjs";
const globalForPrisma = globalThis as unknown as {
prisma: PrismaClient | undefined;
};
export const prisma =
globalForPrisma.prisma ??
new PrismaClient({
log:
env.NODE_ENV === "development" ? ["query", "error", "warn"] : ["error"],
});
if (env.NODE_ENV !== "production") globalForPrisma.prisma = prisma;
-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;
}
}
-25
View File
@@ -1,25 +0,0 @@
export const compactNumberFormatter = (number: number) => {
return Intl.NumberFormat("us", {
notation: "compact",
compactDisplay: "short",
maximumFractionDigits: 2,
}).format(number);
};
export const numberFormatter = (number: number) => {
return Intl.NumberFormat("us", {
notation: "standard",
minimumFractionDigits: 2,
maximumFractionDigits: 2,
}).format(number);
};
export const usdFormatter = (number: number) =>
new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD",
// These options are needed to round to whole numbers if that's what you want.
//minimumFractionDigits: 0, // (this suffices for whole numbers, but will print 2500.10 as $2,500.1)
//maximumFractionDigits: 0, // (causes 2500.99 to be printed as $2,501)
}).format(number);
-54
View File
@@ -1,54 +0,0 @@
import { type Observation } from "@prisma/client";
import { type inferRouterInputs, type inferRouterOutputs } from "@trpc/server";
import { type AppRouter } from "@/src/server/api/root";
import {
type DateTimeAggregationOption,
dateTimeAggregationOptions,
} from "@/src/features/dashboard/lib/timeseries-aggregation";
import { type ObservationReturnType } from "@/src/server/api/routers/traces";
export type NestedObservation = ObservationReturnType & {
children: NestedObservation[];
};
export type TypedObservation = Event | Span | Generation;
export type Event = Observation & {
type: "EVENT";
};
export type Span = Observation & {
type: "SPAN";
endTime: Date; // not null
};
export type LLMChatMessages = { role: string; content: string };
export type Generation = Observation & {
type: "GENERATION";
promptTokens: number;
completionTokens: number;
totalTokens: number;
modelParameters: {
[key: string]: string | number | boolean;
};
};
export type RouterInput = inferRouterInputs<AppRouter>;
export type RouterOutput = inferRouterOutputs<AppRouter>;
export const isUndefinedOrNull = <T>(val?: T | null): val is undefined | null =>
val === undefined || val === null;
export const isNotNullOrUndefined = <T>(
val?: T | null,
): val is Exclude<T, null | undefined> => !isUndefinedOrNull(val);
export function isValidOption(
value: unknown,
): value is DateTimeAggregationOption {
return (
typeof value === "string" &&
dateTimeAggregationOptions.includes(value as DateTimeAggregationOption)
);
}
+7
View File
@@ -0,0 +1,7 @@
Dockerfile
.dockerignore
node_modules
npm-debug.log
README.md
.next
.git
+8 -2
View File
@@ -16,7 +16,7 @@ const config = {
rules: {
"@typescript-eslint/no-non-null-assertion": "off",
"@typescript-eslint/no-confusing-void-expression": "off",
}
},
},
],
parser: "@typescript-eslint/parser",
@@ -35,7 +35,13 @@ const config = {
},
],
"@typescript-eslint/no-unused-vars": ["warn", { argsIgnorePattern: "^_" }],
"react/jsx-key": [
"error",
{
warnOnDuplicates: true,
},
],
},
};
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
+5 -16
View File
@@ -1,19 +1,11 @@
# Base image
FROM node:20-alpine AS base
ARG DATABASE_URL
ARG NEXTAUTH_SECRET
ARG NEXTAUTH_URL
ARG SALT
# It's important to update the index before installing packages to ensure you're getting the latest versions.
# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
RUN apk update && apk upgrade --no-cache libcrypto3 libssl3 libc6-compat
FROM base AS deps
ARG DATABASE_URL
ARG NEXTAUTH_SECRET
ARG NEXTAUTH_URL
ARG SALT
WORKDIR /app
@@ -29,10 +21,6 @@ RUN \
# Rebuild the source code only when needed
FROM base AS builder
ARG DATABASE_URL
ARG NEXTAUTH_SECRET
ARG NEXTAUTH_URL
ARG SALT
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
@@ -46,6 +34,9 @@ RUN rm -f ./src/middleware.ts
# Uncomment the following line in case you want to disable telemetry during the build.
ENV NEXT_TELEMETRY_DISABLED 1
# Disable validation of environment variables during build
ENV DOCKER_BUILD 1
# Generate prisma client
RUN npx prisma generate
@@ -54,10 +45,6 @@ RUN npm run build
# Production image, copy all the files and run next
FROM base AS runner
ARG DATABASE_URL
ARG NEXTAUTH_SECRET
ARG NEXTAUTH_URL
ARG SALT
RUN apk add --no-cache dumb-init
@@ -66,6 +53,8 @@ WORKDIR /app
ENV NODE_ENV production
# Uncomment the following line in case you want to disable telemetry during runtime.
ENV NEXT_TELEMETRY_DISABLED 1
# Needed to re-enable validation of environment variables during runtime
ENV DOCKER_BUILD 0
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
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.9.1",
"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"
}
}
}
}
}
File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 194 KiB

+339
View File
@@ -0,0 +1,339 @@
import type { ColumnType } from "kysely";
export type Generated<T> = T extends ColumnType<infer S, infer I, infer U>
? ColumnType<S, I | undefined, U>
: ColumnType<T, T | undefined, T>;
export type Timestamp = ColumnType<Date, Date | string, Date | string>;
export const MembershipRole = {
OWNER: "OWNER",
ADMIN: "ADMIN",
MEMBER: "MEMBER",
VIEWER: "VIEWER"
} as const;
export type MembershipRole = (typeof MembershipRole)[keyof typeof MembershipRole];
export const ObservationType = {
SPAN: "SPAN",
EVENT: "EVENT",
GENERATION: "GENERATION"
} as const;
export type ObservationType = (typeof ObservationType)[keyof typeof ObservationType];
export const ObservationLevel = {
DEBUG: "DEBUG",
DEFAULT: "DEFAULT",
WARNING: "WARNING",
ERROR: "ERROR"
} as const;
export type ObservationLevel = (typeof ObservationLevel)[keyof typeof ObservationLevel];
export const PricingUnit = {
PER_1000_TOKENS: "PER_1000_TOKENS",
PER_1000_CHARS: "PER_1000_CHARS"
} as const;
export type PricingUnit = (typeof PricingUnit)[keyof typeof PricingUnit];
export const TokenType = {
PROMPT: "PROMPT",
COMPLETION: "COMPLETION",
TOTAL: "TOTAL"
} as const;
export type TokenType = (typeof TokenType)[keyof typeof TokenType];
export const DatasetStatus = {
ACTIVE: "ACTIVE",
ARCHIVED: "ARCHIVED"
} as const;
export type DatasetStatus = (typeof DatasetStatus)[keyof typeof DatasetStatus];
export type Account = {
id: string;
user_id: string;
type: string;
provider: string;
providerAccountId: string;
refresh_token: string | null;
access_token: string | null;
expires_at: number | null;
expires_in: number | null;
ext_expires_in: number | null;
token_type: string | null;
scope: string | null;
id_token: string | null;
session_state: string | null;
};
export type ApiKey = {
id: string;
created_at: Generated<Timestamp>;
note: string | null;
public_key: string;
hashed_secret_key: string;
fast_hashed_secret_key: string | null;
display_secret_key: string;
last_used_at: Timestamp | null;
expires_at: Timestamp | null;
project_id: string;
};
export type AuditLog = {
id: string;
created_at: Generated<Timestamp>;
updated_at: Generated<Timestamp>;
user_id: string;
project_id: string;
user_project_role: MembershipRole;
resource_type: string;
resource_id: string;
action: string;
before: string | null;
after: string | null;
};
export type CronJobs = {
name: string;
last_run: Timestamp | null;
job_started_at: Timestamp | null;
state: string | null;
};
export type Dataset = {
id: string;
name: string;
project_id: string;
created_at: Generated<Timestamp>;
updated_at: Generated<Timestamp>;
};
export type DatasetItem = {
id: string;
status: Generated<DatasetStatus>;
input: unknown;
expected_output: unknown | null;
source_observation_id: string | null;
dataset_id: string;
created_at: Generated<Timestamp>;
updated_at: Generated<Timestamp>;
};
export type DatasetRunItems = {
id: string;
dataset_run_id: string;
dataset_item_id: string;
observation_id: string;
created_at: Generated<Timestamp>;
updated_at: Generated<Timestamp>;
};
export type DatasetRuns = {
id: string;
name: string;
dataset_id: string;
created_at: Generated<Timestamp>;
updated_at: Generated<Timestamp>;
};
export type Events = {
id: string;
created_at: Generated<Timestamp>;
updated_at: Generated<Timestamp>;
project_id: string;
data: unknown;
headers: Generated<unknown>;
url: string | null;
method: string | null;
};
export type Example = {
id: string;
created_at: Generated<Timestamp>;
updated_at: Timestamp;
};
export type Membership = {
project_id: string;
user_id: string;
role: MembershipRole;
created_at: Generated<Timestamp>;
updated_at: Generated<Timestamp>;
};
export type MembershipInvitation = {
id: string;
email: string;
role: MembershipRole;
project_id: string;
sender_id: string | null;
created_at: Generated<Timestamp>;
updated_at: Generated<Timestamp>;
};
export type Model = {
id: string;
created_at: Generated<Timestamp>;
updated_at: Generated<Timestamp>;
project_id: string | null;
model_name: string;
match_pattern: string;
start_date: Timestamp | null;
input_price: string | null;
output_price: string | null;
total_price: string | null;
unit: string;
tokenizer_id: string | null;
tokenizer_config: unknown | null;
};
export type Observation = {
id: string;
trace_id: string | null;
project_id: string;
type: ObservationType;
start_time: Generated<Timestamp>;
end_time: Timestamp | null;
name: string | null;
metadata: unknown | null;
parent_observation_id: string | null;
level: Generated<ObservationLevel>;
status_message: string | null;
version: string | null;
created_at: Generated<Timestamp>;
model: string | null;
internal_model: string | null;
modelParameters: unknown | null;
input: unknown | null;
output: unknown | null;
prompt_tokens: Generated<number>;
completion_tokens: Generated<number>;
total_tokens: Generated<number>;
unit: string | null;
input_cost: string | null;
output_cost: string | null;
total_cost: string | null;
completion_start_time: Timestamp | null;
prompt_id: string | null;
};
export type ObservationView = {
id: string;
trace_id: string | null;
project_id: string;
type: ObservationType;
start_time: Generated<Timestamp>;
end_time: Timestamp | null;
name: string | null;
metadata: unknown | null;
parent_observation_id: string | null;
level: Generated<ObservationLevel>;
status_message: string | null;
version: string | null;
created_at: Generated<Timestamp>;
model: string | null;
modelParameters: unknown | null;
input: unknown | null;
output: unknown | null;
prompt_tokens: Generated<number>;
completion_tokens: Generated<number>;
total_tokens: Generated<number>;
unit: string | null;
completion_start_time: Timestamp | null;
prompt_id: string | null;
model_id: string | null;
input_price: string | null;
output_price: string | null;
total_price: string | null;
calculated_input_cost: string | null;
calculated_output_cost: string | null;
calculated_total_cost: string | null;
latency: number | null;
};
export type Pricing = {
id: string;
model_name: string;
pricing_unit: Generated<PricingUnit>;
price: string;
currency: Generated<string>;
token_type: TokenType;
};
export type Project = {
id: string;
created_at: Generated<Timestamp>;
updated_at: Generated<Timestamp>;
name: string;
cloud_config: unknown | null;
};
export type Prompt = {
id: string;
created_at: Generated<Timestamp>;
updated_at: Generated<Timestamp>;
project_id: string;
created_by: string;
prompt: string;
name: string;
version: number;
is_active: boolean;
config: Generated<unknown>;
};
export type Score = {
id: string;
timestamp: Generated<Timestamp>;
name: string;
value: number;
comment: string | null;
trace_id: string;
observation_id: string | null;
};
export type Session = {
id: string;
session_token: string;
user_id: string;
expires: Timestamp;
};
export type Trace = {
id: string;
external_id: string | null;
timestamp: Generated<Timestamp>;
name: string | null;
user_id: string | null;
metadata: unknown | null;
release: string | null;
version: string | null;
project_id: string;
public: Generated<boolean>;
bookmarked: Generated<boolean>;
tags: Generated<string[]>;
input: unknown | null;
output: unknown | null;
session_id: string | null;
};
export type TraceSession = {
id: string;
created_at: Generated<Timestamp>;
updated_at: Generated<Timestamp>;
project_id: string;
bookmarked: Generated<boolean>;
public: Generated<boolean>;
};
export type User = {
id: string;
name: string | null;
email: string | null;
email_verified: Timestamp | null;
password: string | null;
image: string | null;
admin: Generated<boolean>;
created_at: Generated<Timestamp>;
updated_at: Generated<Timestamp>;
feature_flags: Generated<string[]>;
};
export type VerificationToken = {
identifier: string;
token: string;
expires: Timestamp;
};
export type DB = {
Account: Account;
api_keys: ApiKey;
audit_logs: AuditLog;
cron_jobs: CronJobs;
dataset_items: DatasetItem;
dataset_run_items: DatasetRunItems;
dataset_runs: DatasetRuns;
datasets: Dataset;
events: Events;
Example: Example;
membership_invitations: MembershipInvitation;
memberships: Membership;
models: Model;
observations: Observation;
observations_view: ObservationView;
pricings: Pricing;
projects: Project;
prompts: Prompt;
scores: Score;
Session: Session;
trace_sessions: TraceSession;
traces: Trace;
users: User;
verification_tokens: VerificationToken;
};

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