Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
775e6a8bfc | ||
|
|
5253014fa6 | ||
|
|
1571de133b | ||
|
|
9202f4ec79 | ||
|
|
949e3d1181 | ||
|
|
2d280329c5 | ||
|
|
6e1886055a | ||
|
|
39e4a7533a | ||
|
|
e8787e3f38 | ||
|
|
59055cd311 | ||
|
|
7712b63b95 | ||
|
|
f25d466388 | ||
|
|
b9e18f59d8 | ||
|
|
09f3343db2 | ||
|
|
5ab8e4219f | ||
|
|
40359f0e3f | ||
|
|
817b6d37bc | ||
|
|
8bb73822d3 | ||
|
|
fa53ba3c1a | ||
|
|
086a764083 | ||
|
|
79a9f3c3e3 | ||
|
|
abd46f2d4d | ||
|
|
dfd9565a3f | ||
|
|
ebb8a5a13f | ||
|
|
44104596f6 | ||
|
|
17f6260671 | ||
|
|
0a2bfe5ab5 | ||
|
|
8bd1a4da3e | ||
|
|
31b230d3e0 | ||
|
|
dbe71249e7 | ||
|
|
a9d0486edd | ||
|
|
2bf506a436 | ||
|
|
edca91c12a | ||
|
|
a11e7ddfee | ||
|
|
cb9eb23f36 | ||
|
|
5e942f0208 | ||
|
|
8e0e139848 | ||
|
|
acc1227962 | ||
|
|
d9682511c1 | ||
|
|
00e0b51bc4 | ||
|
|
e63cf84e4f | ||
|
|
63d1051ac2 | ||
|
|
0e056eb072 | ||
|
|
87f7095966 | ||
|
|
5eefe997ae | ||
|
|
e251e60b53 | ||
|
|
adc05eeef4 | ||
|
|
702143fbe2 | ||
|
|
06643f30e5 | ||
|
|
2e496d5429 | ||
|
|
5b62df9122 | ||
|
|
fd189dc66b | ||
|
|
10a3644dcf | ||
|
|
8ca000b225 | ||
|
|
47d41b6a42 | ||
|
|
1d66408c18 | ||
|
|
44d1727dd0 | ||
|
|
bfb2878719 | ||
|
|
67e6b4ce87 | ||
|
|
dcc5bf9c6e | ||
|
|
db357101b7 | ||
|
|
afbd45b9c3 | ||
|
|
b6b37212ce | ||
|
|
76a090241e | ||
|
|
c53abf6aeb | ||
|
|
5cbfd922f9 | ||
|
|
0be269d519 | ||
|
|
d0eeb44b90 | ||
|
|
30ced3ab42 | ||
|
|
2ed6b5a40f | ||
|
|
6eaef75f20 | ||
|
|
31c36565c3 | ||
|
|
d1a1ca7744 | ||
|
|
2dac75d203 | ||
|
|
fab90b36a6 | ||
|
|
597bd6c96b | ||
|
|
ba3bcc9295 | ||
|
|
5f65929a5e | ||
|
|
f1344a4c1a | ||
|
|
4e3b9a82f7 | ||
|
|
7b803619fd | ||
|
|
1ef51b1644 | ||
|
|
fee9e34b7e | ||
|
|
1354db489f | ||
|
|
740a25150c | ||
|
|
47c2d65d12 | ||
|
|
d94e7c1c06 | ||
|
|
38ed98a76d | ||
|
|
92567b765b | ||
|
|
b37396893a | ||
|
|
0fd1eebbff | ||
|
|
f478bb5763 | ||
|
|
1de48b42ba | ||
|
|
4c78450924 | ||
|
|
e360c13763 | ||
|
|
a03a451088 | ||
|
|
e3fa322ecf | ||
|
|
2b20c9bdc2 | ||
|
|
860d05a3f4 | ||
|
|
398174d3a4 | ||
|
|
040ff26853 | ||
|
|
78924f42e2 | ||
|
|
515186e9a2 | ||
|
|
af863bcbd9 | ||
|
|
4e3f97d56e | ||
|
|
159f7560a4 | ||
|
|
fa77bc9daf | ||
|
|
23e55cd90a | ||
|
|
5e39ac49f0 | ||
|
|
75b4c6da1e | ||
|
|
03a8eeaf08 | ||
|
|
0da9738243 | ||
|
|
8d2d242375 | ||
|
|
7b5231db88 | ||
|
|
2925bc77fc | ||
|
|
cfc8d68a57 | ||
|
|
aa38a2cbb8 | ||
|
|
78958ac5f9 | ||
|
|
98506db2b0 | ||
|
|
1ecf3a2a60 | ||
|
|
bca360b738 | ||
|
|
8c44e03cc3 | ||
|
|
5487dc36c9 | ||
|
|
4e2fa5d794 | ||
|
|
8b013c6712 | ||
|
|
76fae866ea | ||
|
|
0e0bf5cfbc | ||
|
|
81872c1fdc | ||
|
|
c06af525bf | ||
|
|
cd30f0c89c | ||
|
|
5bc4f1cbac | ||
|
|
d0f7663ea2 | ||
|
|
7496e2aeb0 | ||
|
|
d39b0214b8 | ||
|
|
9957c51d66 | ||
|
|
0f06a066df | ||
|
|
ff8ccf1d61 | ||
|
|
eeff4a4f68 | ||
|
|
876d43e317 | ||
|
|
3da7f3c8b2 | ||
|
|
6e5d0cee7b | ||
|
|
9f1fafd1bb | ||
|
|
a2cbcbc585 | ||
|
|
e7aa0fbe08 | ||
|
|
30e608244a | ||
|
|
3ec5476c04 | ||
|
|
8c46c79e4f | ||
|
|
231ee5873c | ||
|
|
7a74f7da9d | ||
|
|
82bf0baab7 | ||
|
|
591fb98afb | ||
|
|
e919893c2b | ||
|
|
237076bf92 | ||
|
|
c7b09e7843 | ||
|
|
277e7b7501 | ||
|
|
a01d12c064 | ||
|
|
e1ae79e0d1 | ||
|
|
9804739ff1 | ||
|
|
2d1f104a1c | ||
|
|
2a871d1e75 | ||
|
|
4c749298e6 | ||
|
|
b207712bcd | ||
|
|
472b053c44 | ||
|
|
5b77e5835b | ||
|
|
657bb63c3e | ||
|
|
b101e7c558 | ||
|
|
bac6b13145 | ||
|
|
6817cdab0a | ||
|
|
2d4708921c | ||
|
|
756b2f7501 | ||
|
|
2a685edbfa | ||
|
|
c1c22a9b9b | ||
|
|
ecd3afb4c9 | ||
|
|
362902a69c | ||
|
|
ab14bac8df | ||
|
|
3e92e6b74d | ||
|
|
54f3c224a7 | ||
|
|
e39dda87f9 | ||
|
|
0b8ad96b18 | ||
|
|
a4ba66f329 | ||
|
|
9c473be745 | ||
|
|
4da0b9874a | ||
|
|
8fd6951a19 | ||
|
|
b30734f43c | ||
|
|
293215d1d4 | ||
|
|
ead31c8ca4 | ||
|
|
870336a5ed | ||
|
|
40792d6587 | ||
|
|
820de6f30f | ||
|
|
39fb6d99d4 | ||
|
|
c156a961a2 | ||
|
|
8907056b39 | ||
|
|
7ad6749058 | ||
|
|
2e40330df8 | ||
|
|
3f36fc1191 | ||
|
|
82d7cb9769 | ||
|
|
9bc75b5081 | ||
|
|
3b4811599d | ||
|
|
d6eee1687e | ||
|
|
4b36ff8752 | ||
|
|
64827a0c9d | ||
|
|
fc84da9508 | ||
|
|
3ca321d9f8 | ||
|
|
66df08e232 | ||
|
|
af3cf6d860 | ||
|
|
0edecde6e3 | ||
|
|
5a2fef1fe9 | ||
|
|
28bada800d | ||
|
|
663d67cbd6 | ||
|
|
bd651e81b7 | ||
|
|
f1547dab58 | ||
|
|
34b470f1fe | ||
|
|
040b720dbf | ||
|
|
d56e06d6c9 | ||
|
|
08af244179 | ||
|
|
c821d06099 | ||
|
|
7ed5f71154 | ||
|
|
8c44314f56 | ||
|
|
a3b407ac92 | ||
|
|
b043cf2600 | ||
|
|
d7f75a5e62 | ||
|
|
9951364ff0 | ||
|
|
03cf7bccfc | ||
|
|
4e737ea6cf | ||
|
|
d604ce3ceb | ||
|
|
2c2daf6bb4 | ||
|
|
8ebafda8a4 | ||
|
|
af7384b549 | ||
|
|
9768c2d171 | ||
|
|
f5aec02277 | ||
|
|
b9cf01dd28 | ||
|
|
7c42cf4357 | ||
|
|
72f4b88d15 | ||
|
|
99ce7c5093 | ||
|
|
fcb7b82ba4 | ||
|
|
ac5017c9ae | ||
|
|
00ffddad0f | ||
|
|
28bf40769e | ||
|
|
b65b0e25fc | ||
|
|
62f860d9ef | ||
|
|
3989480a94 | ||
|
|
4a6afddbed | ||
|
|
4c6e8964e3 | ||
|
|
cb900c61f8 | ||
|
|
9bc745d647 | ||
|
|
1b6e9e1c8b | ||
|
|
ce21cf34ae | ||
|
|
bf063a72a0 | ||
|
|
5c2ac78eca | ||
|
|
c6dadda96f | ||
|
|
f831d1ac21 | ||
|
|
1ca4ec7e28 | ||
|
|
a9ca40aa81 | ||
|
|
8b0588a786 | ||
|
|
cc79604302 | ||
|
|
f12532c0a2 | ||
|
|
1c1519555a | ||
|
|
8954cf0c82 | ||
|
|
849428abee | ||
|
|
c014612cca | ||
|
|
803057b5eb | ||
|
|
2152447932 | ||
|
|
70e0b036e5 | ||
|
|
bef666a694 | ||
|
|
601a22d42c | ||
|
|
5fdde72d64 | ||
|
|
f9fc778ee7 | ||
|
|
975ef81bb5 | ||
|
|
28e61fae0b | ||
|
|
0534ccacb2 | ||
|
|
0c5089fd2b | ||
|
|
37c4c1422c | ||
|
|
014da40fbf | ||
|
|
2317334bff | ||
|
|
9ed449288b | ||
|
|
3b4800c37a | ||
|
|
b2ffd05ff8 | ||
|
|
e4594db953 | ||
|
|
4b733c4da8 | ||
|
|
378ac1c1a4 | ||
|
|
9233c7c2d2 | ||
|
|
c2170c0c8d | ||
|
|
7faf0e009f | ||
|
|
86318ab50b | ||
|
|
48d280433a | ||
|
|
45f29eaad8 | ||
|
|
2bca2899f4 | ||
|
|
af6d0f0086 | ||
|
|
3802b1849d | ||
|
|
19d2ee06e9 | ||
|
|
b670abc6bc | ||
|
|
9395e94670 | ||
|
|
684e52e11f | ||
|
|
4048e807af | ||
|
|
0b173f47f7 | ||
|
|
15cad50991 | ||
|
|
747bfae721 | ||
|
|
a01ec32715 | ||
|
|
780fd577c4 | ||
|
|
cd33442168 | ||
|
|
6582dbc645 | ||
|
|
055eb06a4f | ||
|
|
daeaf0a986 | ||
|
|
f199dcb61c | ||
|
|
0ec0cca442 | ||
|
|
f4c75b896b | ||
|
|
16c76b2722 | ||
|
|
64f6051048 | ||
|
|
96dfd86b51 | ||
|
|
b1aaf57ad5 | ||
|
|
fae508d820 | ||
|
|
a6e581d349 | ||
|
|
9e77738a2f | ||
|
|
d15c0a27f5 | ||
|
|
a8626841b5 | ||
|
|
5945a93b7d | ||
|
|
9c447de584 | ||
|
|
48df0e04de | ||
|
|
0897ac753b | ||
|
|
d00c63100e | ||
|
|
e8970bc11c | ||
|
|
eecb253093 | ||
|
|
4e4fbb5101 | ||
|
|
bb4823aa27 | ||
|
|
174d96c100 | ||
|
|
8e59b544c9 | ||
|
|
cffd84f0e7 | ||
|
|
845faee385 | ||
|
|
e45c4af30f | ||
|
|
616544a48c | ||
|
|
75d64b38b3 | ||
|
|
65cdd75282 | ||
|
|
2744028f4c | ||
|
|
3c02c54de2 | ||
|
|
974d2c1007 | ||
|
|
008045c771 | ||
|
|
c6790c6c0e | ||
|
|
909445ce5b | ||
|
|
f4ed4a2635 | ||
|
|
d6206b5269 | ||
|
|
62fa43aa78 | ||
|
|
3c9239a4ab | ||
|
|
476cddb4e1 | ||
|
|
a6c1678da8 | ||
|
|
129805ebde | ||
|
|
59eafb42c3 | ||
|
|
e4695ac717 | ||
|
|
eebd6ea0e9 | ||
|
|
b4a8b08d3d | ||
|
|
ed44b663ff | ||
|
|
720ebe861e | ||
|
|
9a6f8fd75d | ||
|
|
f0da1cfa30 | ||
|
|
0c9ebb3da7 | ||
|
|
3d16d1ac57 | ||
|
|
fa462a8bc4 | ||
|
|
695b65fe0d | ||
|
|
955388e846 | ||
|
|
c6864ed8d9 | ||
|
|
917516fa91 | ||
|
|
19017a6709 | ||
|
|
ca5e6569f9 | ||
|
|
101942b98b | ||
|
|
1188a21b02 | ||
|
|
ec72dd840d | ||
|
|
c2d800ff0e | ||
|
|
dcf159ef82 | ||
|
|
998984b9ed | ||
|
|
022b234e57 | ||
|
|
b8777aa5d1 | ||
|
|
2e84feeab7 | ||
|
|
a508485f88 | ||
|
|
d8bb283a44 | ||
|
|
75ec05e206 | ||
|
|
19f710abe2 | ||
|
|
ad2d6bee66 | ||
|
|
40d0acae5f | ||
|
|
4d387cc35c | ||
|
|
690885c900 | ||
|
|
ef2baa94be | ||
|
|
db6b442832 | ||
|
|
8231ebae4a | ||
|
|
326e8d3189 | ||
|
|
d2001d110d | ||
|
|
3f81c6b9d5 | ||
|
|
991f837ee5 | ||
|
|
062a7f27b8 | ||
|
|
924b326db6 | ||
|
|
2780e66c13 | ||
|
|
c2f51b8d2d | ||
|
|
3a3021a176 | ||
|
|
5dd5a39f90 | ||
|
|
9ee4544e1d | ||
|
|
136f8a3e83 | ||
|
|
eecf0d680b | ||
|
|
d50dbed797 | ||
|
|
bb1dbdf824 | ||
|
|
0991d44525 | ||
|
|
449c9360ac | ||
|
|
cc4a88d6da | ||
|
|
11b2411a5b | ||
|
|
d8a5ebc42e | ||
|
|
9042b005b8 | ||
|
|
7b70b5b678 | ||
|
|
c3ce043d47 | ||
|
|
8c5737ebea | ||
|
|
cb928bf3fc | ||
|
|
dc8a997324 | ||
|
|
31da4bc5a5 | ||
|
|
c0189eecad | ||
|
|
a3f85e75dc | ||
|
|
88ee2f3823 | ||
|
|
0b485ad5d8 | ||
|
|
4e95550411 | ||
|
|
ba9e26181b | ||
|
|
289a7210ee |
@@ -9,7 +9,8 @@ alwaysApply: false
|
||||
- All public api routes are in /web/src/pages/api/public
|
||||
- New api routes should follow these guidelines:
|
||||
- Use [withMiddlewares.ts](mdc:web/src/features/public-api/server/withMiddlewares.ts) as a wrapper
|
||||
- Define types of api request and response in /web/src/features/public-api/types
|
||||
- Define types of api request and response in /web/src/features/public-api/types, use strict() for all zod objects
|
||||
- Add end-to-end test, similar to [datasets-api.servertest.ts](mdc:web/src/__tests__/async/datasets-api.servertest.ts)
|
||||
- Add fern configuration in /fern, learn more about structure here: https://buildwithfern.com/learn/api-definition/fern/overview
|
||||
- Prompt user to regenerate the OpenAPI spec via the fern CLI
|
||||
- Prompt user to regenerate the OpenAPI spec via the fern CLI
|
||||
- Pagination starts at 1, query typing defined in publicApiPaginationZod, return meta in paginationMetaResponseZod
|
||||
+40
-44
@@ -84,6 +84,7 @@ OTEL_SERVICE_NAME="langfuse"
|
||||
# AUTH_GITLAB_ISSUER=
|
||||
# AUTH_GITLAB_CLIENT_AUTH_METHOD=
|
||||
# AUTH_GITLAB_CHECKS=
|
||||
# AUTH_GITLAB_URL=
|
||||
# AUTH_AZURE_AD_CLIENT_ID=
|
||||
# AUTH_AZURE_AD_CLIENT_SECRET=
|
||||
# AUTH_AZURE_AD_TENANT_ID=
|
||||
@@ -156,10 +157,6 @@ OTEL_SERVICE_NAME="langfuse"
|
||||
# LANGFUSE_S3_EVENT_UPLOAD_ACCESS_KEY_ID=
|
||||
# LANGFUSE_S3_EVENT_UPLOAD_SECRET_ACCESS_KEY=
|
||||
|
||||
# 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
|
||||
|
||||
# Automated provisioning of default resources
|
||||
# LANGFUSE_INIT_ORG_ID=org-id
|
||||
# LANGFUSE_INIT_ORG_NAME=org-name
|
||||
@@ -171,7 +168,32 @@ OTEL_SERVICE_NAME="langfuse"
|
||||
# LANGFUSE_INIT_USER_NAME=User Name
|
||||
# LANGFUSE_INIT_USER_PASSWORD=password
|
||||
|
||||
# Redis configuration
|
||||
# REDIS_HOST=
|
||||
# REDIS_PORT=
|
||||
# REDIS_AUTH=
|
||||
# REDIS_CONNECTION_STRING=
|
||||
# REDIS_ENABLE_AUTO_PIPELINING=
|
||||
|
||||
# Cache configuration
|
||||
# LANGFUSE_CACHE_API_KEY_ENABLED=
|
||||
# LANGFUSE_CACHE_API_KEY_TTL_SECONDS=
|
||||
# LANGFUSE_CACHE_PROMPT_ENABLED=
|
||||
# LANGFUSE_CACHE_PROMPT_TTL_SECONDS=
|
||||
|
||||
# Clickhouse configuration
|
||||
# CLICKHOUSE_URL=
|
||||
# CLICKHOUSE_CLUSTER_NAME=default
|
||||
# CLICKHOUSE_DB=default
|
||||
# CLICKHOUSE_USER=
|
||||
# CLICKHOUSE_PASSWORD=
|
||||
# CLICKHOUSE_CLUSTER_ENABLED=true
|
||||
|
||||
# Ingestion configuration
|
||||
# LANGFUSE_INGESTION_QUEUE_DELAY_MS=
|
||||
# LANGFUSE_INGESTION_CLICKHOUSE_WRITE_BATCH_SIZE=
|
||||
# LANGFUSE_INGESTION_CLICKHOUSE_WRITE_INTERVAL_MS=
|
||||
# LANGFUSE_INGESTION_CLICKHOUSE_MAX_ATTEMPTS=
|
||||
|
||||
### START Enterprise Edition Configuration
|
||||
|
||||
@@ -189,21 +211,12 @@ OTEL_SERVICE_NAME="langfuse"
|
||||
# LANGFUSE_UI_DEFAULT_BASE_URL_OPENAI=https://api.openai.com/v1
|
||||
# LANGFUSE_UI_DEFAULT_BASE_URL_ANTHROPIC=https://api.anthropic.com
|
||||
# LANGFUSE_UI_DEFAULT_BASE_URL_AZURE_OPENAI=https://{instanceName}.openai.azure.com/openai/deployments
|
||||
# LANGFUSE_UI_VISIBLE_PRODUCT_MODULES=
|
||||
# LANGFUSE_UI_HIDDEN_PRODUCT_MODULES=
|
||||
|
||||
### END Enterprise Edition Configuration
|
||||
|
||||
|
||||
|
||||
### START Envs to be deprecated in Langfuse v3.0
|
||||
|
||||
# Disable the expensive analytics queries and related features
|
||||
# LANGFUSE_DISABLE_EXPENSIVE_POSTGRES_QUERIES="true"
|
||||
|
||||
### END Envs to be deprecated in Langfuse v3.0
|
||||
|
||||
|
||||
|
||||
|
||||
### START Langfuse Cloud Config
|
||||
# Used for Langfuse Cloud deployments
|
||||
# Not recommended for self-hosted deployments as these are NOT COVERED BY SEMANTIC VERSIONING
|
||||
@@ -235,24 +248,14 @@ OTEL_SERVICE_NAME="langfuse"
|
||||
# NEXT_PUBLIC_DEMO_ORG_ID=
|
||||
# NEXT_PUBLIC_DEMO_PROJECT_ID=
|
||||
|
||||
# Crisp chat
|
||||
# NEXT_PUBLIC_CRISP_WEBSITE_ID=
|
||||
# Plain Chat
|
||||
# NEXT_PUBLIC_PLAIN_APP_ID=
|
||||
# PLAIN_AUTHENTICATION_SECRET=
|
||||
|
||||
# Admin API
|
||||
# ADMIN_API_KEY=
|
||||
|
||||
# Redis
|
||||
# REDIS_HOST=
|
||||
# REDIS_PORT=
|
||||
# REDIS_AUTH=
|
||||
# REDIS_CONNECTION_STRING=
|
||||
# REDIS_ENABLE_AUTO_PIPELINING=
|
||||
|
||||
# Cache configuration
|
||||
# LANGFUSE_CACHE_API_KEY_ENABLED=
|
||||
# LANGFUSE_CACHE_API_KEY_TTL_SECONDS=
|
||||
# LANGFUSE_CACHE_PROMPT_ENABLED=
|
||||
# LANGFUSE_CACHE_PROMPT_TTL_SECONDS=
|
||||
# LANGFUSE_CACHE_MODEL_MATCH_ENABLED=
|
||||
# LANGFUSE_CACHE_MODEL_MATCH_TTL_SECONDS=
|
||||
|
||||
# Rate limiting
|
||||
# LANGFUSE_RATE_LIMITS_ENABLED=
|
||||
@@ -261,22 +264,15 @@ OTEL_SERVICE_NAME="langfuse"
|
||||
# STRIPE_SECRET_KEY=
|
||||
# STRIPE_WEBHOOK_SIGNING_SECRET=
|
||||
|
||||
# Betterstack Status Page
|
||||
# BETTERSTACK_UPTIME_API_KEY=
|
||||
# BETTERSTACK_UPTIME_STATUS_PAGE_ID=
|
||||
|
||||
### END Langfuse Cloud Config
|
||||
|
||||
|
||||
## START Langfuse V3 Ingestion
|
||||
### START Langfuse CI Config
|
||||
|
||||
# Clickhouse
|
||||
# CLICKHOUSE_MIGRATION_URL=
|
||||
# CLICKHOUSE_URL=
|
||||
# CLICKHOUSE_USER=
|
||||
# CLICKHOUSE_PASSWORD=
|
||||
# CLICKHOUSE_DB=
|
||||
# LANGFUSE_INIT_ORG_CLOUD_PLAN=
|
||||
|
||||
# Ingestion
|
||||
# LANGFUSE_INGESTION_QUEUE_DELAY_MS=
|
||||
# LANGFUSE_INGESTION_CLICKHOUSE_WRITE_BATCH_SIZE=
|
||||
# LANGFUSE_INGESTION_CLICKHOUSE_WRITE_INTERVAL_MS=
|
||||
# LANGFUSE_INGESTION_CLICKHOUSE_MAX_ATTEMPTS=
|
||||
|
||||
## END Langfuse V3 Ingestion
|
||||
### END Langfuse CI Config
|
||||
|
||||
@@ -15,6 +15,10 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
environment: ${{ inputs.environment }}
|
||||
steps:
|
||||
- name: Set Swap Space
|
||||
uses: pierotofy/set-swap-space@master
|
||||
with:
|
||||
swap-size-gb: 10
|
||||
- name: Get app name
|
||||
uses: winterjung/split@v2
|
||||
id: split
|
||||
@@ -52,10 +56,11 @@ jobs:
|
||||
--build-arg NEXT_PUBLIC_BUILD_ID=${{ github.sha }} \
|
||||
--build-arg NEXT_PUBLIC_POSTHOG_KEY=${{ vars.NEXT_PUBLIC_POSTHOG_KEY }} \
|
||||
--build-arg NEXT_PUBLIC_POSTHOG_HOST=${{ vars.NEXT_PUBLIC_POSTHOG_HOST }} \
|
||||
--build-arg NEXT_PUBLIC_CRISP_WEBSITE_ID=${{ vars.NEXT_PUBLIC_CRISP_WEBSITE_ID }} \
|
||||
--build-arg NEXT_PUBLIC_PLAIN_APP_ID=${{ vars.NEXT_PUBLIC_PLAIN_APP_ID }} \
|
||||
--build-arg SENTRY_AUTH_TOKEN=${{ secrets.SENTRY_AUTH_TOKEN }} \
|
||||
--build-arg SENTRY_ORG=${{ vars.SENTRY_ORG }} \
|
||||
--build-arg SENTRY_PROJECT=${{ vars.SENTRY_PROJECT }} \
|
||||
--build-arg NEXT_PUBLIC_LANGFUSE_TRACING_SAMPLE_RATE=${{ vars.NEXT_PUBLIC_LANGFUSE_TRACING_SAMPLE_RATE }} \
|
||||
.
|
||||
docker push $REGISTRY/$REPOSITORY:$IMAGE_TAG
|
||||
- name: Render AWS ECS Task Definition
|
||||
|
||||
@@ -21,6 +21,7 @@ on:
|
||||
- staging
|
||||
- prod-eu
|
||||
- prod-us
|
||||
- prod-hipaa
|
||||
required: true
|
||||
|
||||
concurrency:
|
||||
@@ -78,7 +79,7 @@ jobs:
|
||||
return `["staging"]`
|
||||
}
|
||||
if (context.ref === "refs/heads/production") {
|
||||
return `["prod-eu", "prod-us"]`
|
||||
return `["prod-eu", "prod-us", "prod-hipaa"]`
|
||||
}
|
||||
}
|
||||
return "[]"
|
||||
|
||||
@@ -134,14 +134,14 @@ jobs:
|
||||
grep -v -e '^LANGFUSE_S3_BATCH_EXPORT_ENABLED=' -e '^NEXT_PUBLIC_LANGFUSE_RUN_NEXT_INIT=' .env.dev.example > .env
|
||||
echo "LANGFUSE_INGESTION_QUEUE_DELAY_MS=1" >> .env
|
||||
echo "LANGFUSE_INGESTION_CLICKHOUSE_WRITE_INTERVAL_MS=1" >> .env
|
||||
- name: Run + migrate
|
||||
- name: Run dev containers
|
||||
run: |
|
||||
docker compose -f docker-compose.dev.yml up -d
|
||||
sleep 5 # Wait for PostgreSQL to accept connections
|
||||
docker compose ps
|
||||
env:
|
||||
POSTGRES_VERSION: ${{ matrix.postgres-version }}
|
||||
- name: Seed DB
|
||||
- name: Migrate DB
|
||||
run: |
|
||||
pnpm run db:migrate
|
||||
pnpm --filter=shared ch:up
|
||||
@@ -152,6 +152,7 @@ jobs:
|
||||
env:
|
||||
LANGFUSE_INIT_ORG_ID: "seed-org-id"
|
||||
LANGFUSE_INIT_ORG_NAME: "Seed Org"
|
||||
LANGFUSE_INIT_ORG_CLOUD_PLAN: "Team"
|
||||
LANGFUSE_INIT_PROJECT_ID: "7a88fb47-b4e2-43b8-a06c-a5ce950dc53a"
|
||||
LANGFUSE_INIT_PROJECT_NAME: "Seed Project"
|
||||
LANGFUSE_INIT_PROJECT_PUBLIC_KEY: "pk-lf-1234567890"
|
||||
@@ -211,14 +212,17 @@ jobs:
|
||||
grep -v -e '^LANGFUSE_S3_BATCH_EXPORT_ENABLED=' -e '^NEXT_PUBLIC_LANGFUSE_RUN_NEXT_INIT=' .env.dev${{ matrix.blob-provider }}.example > .env
|
||||
echo "LANGFUSE_INGESTION_QUEUE_DELAY_MS=1" >> .env
|
||||
echo "LANGFUSE_INGESTION_CLICKHOUSE_WRITE_INTERVAL_MS=1" >> .env
|
||||
- name: Run + migrate
|
||||
echo "LANGFUSE_TRACE_DELETE_CONCURRENCY=100" >> .env
|
||||
echo "ADMIN_API_KEY=admin-api-key" >> .env
|
||||
echo "LANGFUSE_EE_LICENSE_KEY=langfuse_ee_test" >> .env
|
||||
- name: Run dev containers
|
||||
run: |
|
||||
docker compose -f docker-compose.dev${{ matrix.blob-provider }}.yml up -d
|
||||
sleep 5 # Wait for PostgreSQL to accept connections
|
||||
docker compose ps
|
||||
env:
|
||||
POSTGRES_VERSION: ${{ matrix.postgres-version }}
|
||||
- name: Seed DB
|
||||
- name: Migrate DB
|
||||
run: |
|
||||
pnpm run db:migrate
|
||||
pnpm --filter=shared ch:up
|
||||
@@ -229,6 +233,7 @@ jobs:
|
||||
env:
|
||||
LANGFUSE_INIT_ORG_ID: "seed-org-id"
|
||||
LANGFUSE_INIT_ORG_NAME: "Seed Org"
|
||||
LANGFUSE_INIT_ORG_CLOUD_PLAN: "Team"
|
||||
LANGFUSE_INIT_PROJECT_ID: "7a88fb47-b4e2-43b8-a06c-a5ce950dc53a"
|
||||
LANGFUSE_INIT_PROJECT_NAME: "Seed Project"
|
||||
LANGFUSE_INIT_PROJECT_PUBLIC_KEY: "pk-lf-1234567890"
|
||||
@@ -336,14 +341,28 @@ jobs:
|
||||
run: |
|
||||
cp .env.dev.example .env
|
||||
cp .env.dev.example web/.env
|
||||
- name: Install golang-migrate for Clickhouse migrations
|
||||
run: |
|
||||
curl -L https://github.com/golang-migrate/migrate/releases/download/v4.18.2/migrate.linux-amd64.tar.gz | tar xvz
|
||||
sudo mv migrate /usr/bin/migrate
|
||||
which migrate
|
||||
- name: Run + migrate
|
||||
run: |
|
||||
docker compose -f docker-compose.dev.yml up -d
|
||||
docker compose ps
|
||||
sleep 5 # Wait for PostgreSQL to accept connections
|
||||
- name: Ensure Docker dependencies are healthy
|
||||
run: |
|
||||
if docker-compose ps | grep "(unhealthy)"; then
|
||||
echo "One or more services are unhealthy"
|
||||
exit 1
|
||||
else
|
||||
echo "All services are healthy"
|
||||
fi
|
||||
- name: Seed DB
|
||||
run: |
|
||||
pnpm run db:migrate
|
||||
pnpm --filter=shared run ch:up
|
||||
pnpm run db:seed
|
||||
- name: Build
|
||||
run: pnpm run build
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
name: Close inactive issues
|
||||
on:
|
||||
schedule:
|
||||
- cron: "30 1 * * *"
|
||||
|
||||
jobs:
|
||||
close-issues:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write
|
||||
pull-requests: write
|
||||
steps:
|
||||
- uses: actions/stale@v9
|
||||
with:
|
||||
days-before-issue-stale: 30
|
||||
days-before-issue-close: 14
|
||||
stale-issue-label: "stale"
|
||||
stale-issue-message: "This issue is stale because it has been open for 30 days with no activity."
|
||||
close-issue-message: "This issue was closed because it has been inactive for 14 days since being marked as stale. Please reopen if the issue persists."
|
||||
days-before-pr-stale: -1
|
||||
days-before-pr-close: -1
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
+3
-1
@@ -62,4 +62,6 @@ node_modules
|
||||
**/.next/*
|
||||
**/.turbo/*
|
||||
.yarn
|
||||
.turbo
|
||||
.turbo
|
||||
|
||||
web/test-results/*
|
||||
@@ -0,0 +1,16 @@
|
||||
# Codex Guidelines for Langfuse
|
||||
|
||||
Langfuse is an **open source LLM engineering** platform for developing, monitoring, evaluating and debugging AI applications. See the README for more details.
|
||||
|
||||
## Linting
|
||||
- Run `pnpm run lint` to lint all packages.
|
||||
- Fix issues automatically with `pnpm run lint:fix`.
|
||||
|
||||
## Tests
|
||||
- Codex cannot run the test suite because it depends on Docker-based infrastructure that is unavailable in this environment.
|
||||
|
||||
## Cursor Rules
|
||||
- Additional folder-specific rules live in `.cursor/rules/`.
|
||||
|
||||
## Commits
|
||||
- Follow [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) when crafting commit messages.
|
||||
+2
-2
@@ -27,7 +27,7 @@ The maintainers are available on [Discord](https://langfuse.com/discord) in case
|
||||
|
||||
## 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. Large changes that were not discussed in an issue may be rejected.
|
||||
_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. 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.
|
||||
|
||||
@@ -83,7 +83,7 @@ Full database schema: [packages/shared/prisma/schema.prisma](packages/shared/pri
|
||||
We built a monorepo using [pnpm](https://pnpm.io/motivation) and [turbo](https://turbo.build/repo/docs) to manage the dependencies and build process. The monorepo 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.
|
||||
- `worker`: contains an application for asynchronous processing of tasks.
|
||||
- `packages`:
|
||||
- `shared`: contains shared code between the above packages.
|
||||
- `config-eslint`: contains eslint configurations which are shared between the above packages.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
services:
|
||||
clickhouse:
|
||||
image: clickhouse/clickhouse-server
|
||||
image: clickhouse/clickhouse-server:24.3
|
||||
user: "101:101"
|
||||
environment:
|
||||
CLICKHOUSE_DB: default
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
services:
|
||||
clickhouse:
|
||||
image: clickhouse/clickhouse-server
|
||||
image: clickhouse/clickhouse-server:24.3
|
||||
user: "101:101"
|
||||
environment:
|
||||
CLICKHOUSE_DB: default
|
||||
@@ -10,8 +10,8 @@ services:
|
||||
- langfuse_clickhouse_data:/var/lib/clickhouse
|
||||
- langfuse_clickhouse_logs:/var/log/clickhouse-server
|
||||
ports:
|
||||
- "8123:8123"
|
||||
- "9000:9000"
|
||||
- 127.0.0.1:8123:8123
|
||||
- 127.0.0.1:9000:9000
|
||||
depends_on:
|
||||
- postgres
|
||||
|
||||
@@ -24,8 +24,8 @@ services:
|
||||
MINIO_ACCESS_KEY: minio
|
||||
MINIO_SECRET_KEY: miniosecret
|
||||
ports:
|
||||
- "9090:9000"
|
||||
- "9091:9001"
|
||||
- 127.0.0.1:9090:9000
|
||||
- 127.0.0.1:9091:9001
|
||||
volumes:
|
||||
- langfuse_minio_data:/data
|
||||
healthcheck:
|
||||
@@ -41,7 +41,7 @@ services:
|
||||
command: >
|
||||
--requirepass ${REDIS_AUTH:-myredissecret}
|
||||
ports:
|
||||
- 6379:6379
|
||||
- 127.0.0.1:6379:6379
|
||||
|
||||
postgres:
|
||||
image: postgres:${POSTGRES_VERSION:-latest}
|
||||
@@ -57,7 +57,7 @@ services:
|
||||
- POSTGRES_PASSWORD=postgres
|
||||
- POSTGRES_DB=postgres
|
||||
ports:
|
||||
- 5432:5432
|
||||
- 127.0.0.1:5432:5432
|
||||
volumes:
|
||||
- langfuse_postgres_data:/var/lib/postgresql/data
|
||||
|
||||
|
||||
+35
-20
@@ -1,3 +1,8 @@
|
||||
# Make sure to update the credential placeholders with your own secrets.
|
||||
# We mark them with # CHANGEME in the file below.
|
||||
# In addition, we recommend to restrict inbound traffic on the host to langfuse-web (port 3000) and minio (port 9090) only.
|
||||
# All other components are bound to localhost (127.0.0.1) to only accept connections from the local machine.
|
||||
# External connections from other machines will not be able to reach these services directly.
|
||||
services:
|
||||
langfuse-worker:
|
||||
image: langfuse/langfuse-worker:3
|
||||
@@ -12,37 +17,46 @@ services:
|
||||
clickhouse:
|
||||
condition: service_healthy
|
||||
ports:
|
||||
- "3030:3030"
|
||||
- 127.0.0.1:3030:3030
|
||||
environment: &langfuse-worker-env
|
||||
DATABASE_URL: postgresql://postgres:postgres@postgres:5432/postgres
|
||||
SALT: "mysalt"
|
||||
ENCRYPTION_KEY: "0000000000000000000000000000000000000000000000000000000000000000" # generate via `openssl rand -hex 32`
|
||||
DATABASE_URL: postgresql://postgres:postgres@postgres:5432/postgres # CHANGEME
|
||||
SALT: "mysalt" # CHANGEME
|
||||
ENCRYPTION_KEY: "0000000000000000000000000000000000000000000000000000000000000000" # CHANGEME: generate via `openssl rand -hex 32`
|
||||
TELEMETRY_ENABLED: ${TELEMETRY_ENABLED:-true}
|
||||
LANGFUSE_ENABLE_EXPERIMENTAL_FEATURES: ${LANGFUSE_ENABLE_EXPERIMENTAL_FEATURES:-true}
|
||||
CLICKHOUSE_MIGRATION_URL: ${CLICKHOUSE_MIGRATION_URL:-clickhouse://clickhouse:9000}
|
||||
CLICKHOUSE_URL: ${CLICKHOUSE_URL:-http://clickhouse:8123}
|
||||
CLICKHOUSE_USER: ${CLICKHOUSE_USER:-clickhouse}
|
||||
CLICKHOUSE_PASSWORD: ${CLICKHOUSE_PASSWORD:-clickhouse}
|
||||
CLICKHOUSE_PASSWORD: ${CLICKHOUSE_PASSWORD:-clickhouse} # CHANGEME
|
||||
CLICKHOUSE_CLUSTER_ENABLED: ${CLICKHOUSE_CLUSTER_ENABLED:-false}
|
||||
LANGFUSE_S3_EVENT_UPLOAD_BUCKET: ${LANGFUSE_S3_EVENT_UPLOAD_BUCKET:-langfuse}
|
||||
LANGFUSE_S3_EVENT_UPLOAD_REGION: ${LANGFUSE_S3_EVENT_UPLOAD_REGION:-auto}
|
||||
LANGFUSE_S3_EVENT_UPLOAD_ACCESS_KEY_ID: ${LANGFUSE_S3_EVENT_UPLOAD_ACCESS_KEY_ID:-minio}
|
||||
LANGFUSE_S3_EVENT_UPLOAD_SECRET_ACCESS_KEY: ${LANGFUSE_S3_EVENT_UPLOAD_SECRET_ACCESS_KEY:-miniosecret}
|
||||
LANGFUSE_S3_EVENT_UPLOAD_SECRET_ACCESS_KEY: ${LANGFUSE_S3_EVENT_UPLOAD_SECRET_ACCESS_KEY:-miniosecret} # CHANGEME
|
||||
LANGFUSE_S3_EVENT_UPLOAD_ENDPOINT: ${LANGFUSE_S3_EVENT_UPLOAD_ENDPOINT:-http://minio:9000}
|
||||
LANGFUSE_S3_EVENT_UPLOAD_FORCE_PATH_STYLE: ${LANGFUSE_S3_EVENT_UPLOAD_FORCE_PATH_STYLE:-true}
|
||||
LANGFUSE_S3_EVENT_UPLOAD_PREFIX: ${LANGFUSE_S3_EVENT_UPLOAD_PREFIX:-events/}
|
||||
LANGFUSE_S3_MEDIA_UPLOAD_BUCKET: ${LANGFUSE_S3_MEDIA_UPLOAD_BUCKET:-langfuse}
|
||||
LANGFUSE_S3_MEDIA_UPLOAD_REGION: ${LANGFUSE_S3_MEDIA_UPLOAD_REGION:-auto}
|
||||
LANGFUSE_S3_MEDIA_UPLOAD_ACCESS_KEY_ID: ${LANGFUSE_S3_MEDIA_UPLOAD_ACCESS_KEY_ID:-minio}
|
||||
LANGFUSE_S3_MEDIA_UPLOAD_SECRET_ACCESS_KEY: ${LANGFUSE_S3_MEDIA_UPLOAD_SECRET_ACCESS_KEY:-miniosecret}
|
||||
LANGFUSE_S3_MEDIA_UPLOAD_ENDPOINT: ${LANGFUSE_S3_MEDIA_UPLOAD_ENDPOINT:-http://minio:9000}
|
||||
LANGFUSE_S3_MEDIA_UPLOAD_SECRET_ACCESS_KEY: ${LANGFUSE_S3_MEDIA_UPLOAD_SECRET_ACCESS_KEY:-miniosecret} # CHANGEME
|
||||
LANGFUSE_S3_MEDIA_UPLOAD_ENDPOINT: ${LANGFUSE_S3_MEDIA_UPLOAD_ENDPOINT:-http://localhost:9090}
|
||||
LANGFUSE_S3_MEDIA_UPLOAD_FORCE_PATH_STYLE: ${LANGFUSE_S3_MEDIA_UPLOAD_FORCE_PATH_STYLE:-true}
|
||||
LANGFUSE_S3_MEDIA_UPLOAD_PREFIX: ${LANGFUSE_S3_MEDIA_UPLOAD_PREFIX:-media/}
|
||||
LANGFUSE_S3_BATCH_EXPORT_ENABLED: ${LANGFUSE_S3_BATCH_EXPORT_ENABLED:-false}
|
||||
LANGFUSE_S3_BATCH_EXPORT_BUCKET: ${LANGFUSE_S3_BATCH_EXPORT_BUCKET:-langfuse}
|
||||
LANGFUSE_S3_BATCH_EXPORT_PREFIX: ${LANGFUSE_S3_BATCH_EXPORT_PREFIX:-exports/}
|
||||
LANGFUSE_S3_BATCH_EXPORT_REGION: ${LANGFUSE_S3_BATCH_EXPORT_REGION:-auto}
|
||||
LANGFUSE_S3_BATCH_EXPORT_ENDPOINT: ${LANGFUSE_S3_BATCH_EXPORT_ENDPOINT:-http://minio:9000}
|
||||
LANGFUSE_S3_BATCH_EXPORT_EXTERNAL_ENDPOINT: ${LANGFUSE_S3_BATCH_EXPORT_EXTERNAL_ENDPOINT:-http://localhost:9090}
|
||||
LANGFUSE_S3_BATCH_EXPORT_ACCESS_KEY_ID: ${LANGFUSE_S3_BATCH_EXPORT_ACCESS_KEY_ID:-minio}
|
||||
LANGFUSE_S3_BATCH_EXPORT_SECRET_ACCESS_KEY: ${LANGFUSE_S3_BATCH_EXPORT_SECRET_ACCESS_KEY:-miniosecret} # CHANGEME
|
||||
LANGFUSE_S3_BATCH_EXPORT_FORCE_PATH_STYLE: ${LANGFUSE_S3_BATCH_EXPORT_FORCE_PATH_STYLE:-true}
|
||||
LANGFUSE_INGESTION_QUEUE_DELAY_MS: ${LANGFUSE_INGESTION_QUEUE_DELAY_MS:-}
|
||||
LANGFUSE_INGESTION_CLICKHOUSE_WRITE_INTERVAL_MS: ${LANGFUSE_INGESTION_CLICKHOUSE_WRITE_INTERVAL_MS:-}
|
||||
REDIS_HOST: ${REDIS_HOST:-redis}
|
||||
REDIS_PORT: ${REDIS_PORT:-6379}
|
||||
REDIS_AUTH: ${REDIS_AUTH:-myredissecret}
|
||||
REDIS_AUTH: ${REDIS_AUTH:-myredissecret} # CHANGEME
|
||||
REDIS_TLS_ENABLED: ${REDIS_TLS_ENABLED:-false}
|
||||
REDIS_TLS_CA: ${REDIS_TLS_CA:-/certs/ca.crt}
|
||||
REDIS_TLS_CERT: ${REDIS_TLS_CERT:-/certs/redis.crt}
|
||||
@@ -53,11 +67,11 @@ services:
|
||||
restart: always
|
||||
depends_on: *langfuse-depends-on
|
||||
ports:
|
||||
- "3000:3000"
|
||||
- 3000:3000
|
||||
environment:
|
||||
<<: *langfuse-worker-env
|
||||
NEXTAUTH_URL: http://localhost:3000
|
||||
NEXTAUTH_SECRET: mysecret
|
||||
NEXTAUTH_SECRET: mysecret # CHANGEME
|
||||
LANGFUSE_INIT_ORG_ID: ${LANGFUSE_INIT_ORG_ID:-}
|
||||
LANGFUSE_INIT_ORG_NAME: ${LANGFUSE_INIT_ORG_NAME:-}
|
||||
LANGFUSE_INIT_PROJECT_ID: ${LANGFUSE_INIT_PROJECT_ID:-}
|
||||
@@ -75,13 +89,13 @@ services:
|
||||
environment:
|
||||
CLICKHOUSE_DB: default
|
||||
CLICKHOUSE_USER: clickhouse
|
||||
CLICKHOUSE_PASSWORD: clickhouse
|
||||
CLICKHOUSE_PASSWORD: clickhouse # CHANGEME
|
||||
volumes:
|
||||
- langfuse_clickhouse_data:/var/lib/clickhouse
|
||||
- langfuse_clickhouse_logs:/var/log/clickhouse-server
|
||||
ports:
|
||||
- "8123:8123"
|
||||
- "9000:9000"
|
||||
- 127.0.0.1:8123:8123
|
||||
- 127.0.0.1:9000:9000
|
||||
healthcheck:
|
||||
test: wget --no-verbose --tries=1 --spider http://localhost:8123/ping || exit 1
|
||||
interval: 5s
|
||||
@@ -97,10 +111,10 @@ services:
|
||||
command: -c 'mkdir -p /data/langfuse && minio server --address ":9000" --console-address ":9001" /data'
|
||||
environment:
|
||||
MINIO_ROOT_USER: minio
|
||||
MINIO_ROOT_PASSWORD: miniosecret
|
||||
MINIO_ROOT_PASSWORD: miniosecret # CHANGEME
|
||||
ports:
|
||||
- "9090:9000"
|
||||
- "9091:9001"
|
||||
- 9090:9000
|
||||
- 127.0.0.1:9091:9001
|
||||
volumes:
|
||||
- langfuse_minio_data:/data
|
||||
healthcheck:
|
||||
@@ -113,10 +127,11 @@ services:
|
||||
redis:
|
||||
image: redis:7
|
||||
restart: always
|
||||
# CHANGEME: row below to secure redis password
|
||||
command: >
|
||||
--requirepass ${REDIS_AUTH:-myredissecret}
|
||||
ports:
|
||||
- 6379:6379
|
||||
- 127.0.0.1:6379:6379
|
||||
healthcheck:
|
||||
test: ["CMD", "redis-cli", "ping"]
|
||||
interval: 3s
|
||||
@@ -133,10 +148,10 @@ services:
|
||||
retries: 10
|
||||
environment:
|
||||
POSTGRES_USER: postgres
|
||||
POSTGRES_PASSWORD: postgres
|
||||
POSTGRES_PASSWORD: postgres # CHANGEME
|
||||
POSTGRES_DB: postgres
|
||||
ports:
|
||||
- 5432:5432
|
||||
- 127.0.0.1:5432:5432
|
||||
volumes:
|
||||
- langfuse_postgres_data:/var/lib/postgresql/data
|
||||
|
||||
|
||||
+2
-2
@@ -28,9 +28,9 @@
|
||||
"@opentelemetry/api": ">=1.0.0 <1.10.0",
|
||||
"axios": "^1.8.2",
|
||||
"https-proxy-agent": "^7.0.6",
|
||||
"next": "^14.2.21",
|
||||
"next": "^14.2.26",
|
||||
"next-auth": "^4.24.11",
|
||||
"zod": "^3.23.8"
|
||||
"zod": "^3.24.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@repo/eslint-config": "workspace:*",
|
||||
|
||||
@@ -14,13 +14,16 @@ types:
|
||||
CreateScoreRequest:
|
||||
properties:
|
||||
id: optional<string>
|
||||
traceId: string
|
||||
traceId: optional<string>
|
||||
sessionId: optional<string>
|
||||
observationId: optional<string>
|
||||
datasetRunId: optional<string>
|
||||
name: string
|
||||
value:
|
||||
type: CreateScoreValue
|
||||
docs: The value of the score. Must be passed as string for categorical scores, and numeric for boolean and numeric scores. Boolean score values must equal either 1 or 0 (true or false)
|
||||
observationId: optional<string>
|
||||
comment: optional<string>
|
||||
metadata: optional<unknown>
|
||||
dataType:
|
||||
type: optional<ScoreDataType>
|
||||
docs: When set, must match the score value's type. If not set, will be inferred from the score value or config
|
||||
@@ -64,62 +67,15 @@ types:
|
||||
dataType: "BOOLEAN"
|
||||
configId: "1234-5678-90ab-cdef"
|
||||
traceId: "cdef-1234-5678-90ab"
|
||||
BaseScore:
|
||||
properties:
|
||||
id: string
|
||||
traceId: string
|
||||
name: string
|
||||
source: ScoreSource
|
||||
observationId: optional<string>
|
||||
timestamp: datetime
|
||||
createdAt: datetime
|
||||
updatedAt: datetime
|
||||
authorUserId: optional<string>
|
||||
comment: optional<string>
|
||||
configId:
|
||||
type: optional<string>
|
||||
docs: Reference a score config on a score. When set, config and score name must be equal and value must comply to optionally defined numerical range
|
||||
NumericScore:
|
||||
extends: BaseScore
|
||||
properties:
|
||||
value:
|
||||
type: double
|
||||
docs: The numeric value of the score
|
||||
BooleanScore:
|
||||
extends: BaseScore
|
||||
properties:
|
||||
value:
|
||||
type: double
|
||||
docs: The numeric value of the score. Equals 1 for "True" and 0 for "False"
|
||||
stringValue:
|
||||
type: string
|
||||
docs: The string representation of the score value. Is inferred from the numeric value and equals "True" or "False"
|
||||
CategoricalScore:
|
||||
extends: BaseScore
|
||||
properties:
|
||||
value:
|
||||
type: optional<double>
|
||||
docs: Only defined if a config is linked. Represents the numeric category mapping of the stringValue
|
||||
stringValue:
|
||||
type: string
|
||||
docs: The string representation of the score value. If no config is linked, can be any string. Otherwise, must map to a config category
|
||||
Score:
|
||||
discriminant: "dataType"
|
||||
union:
|
||||
NUMERIC:
|
||||
type: NumericScore
|
||||
docs: "Score with NUMERIC data type"
|
||||
CATEGORICAL:
|
||||
type: CategoricalScore
|
||||
docs: "Score with CATEGORICAL data type"
|
||||
BOOLEAN:
|
||||
type: BooleanScore
|
||||
docs: "Score with BOOLEAN data type"
|
||||
ScoreSource:
|
||||
enum:
|
||||
- ANNOTATION
|
||||
- API
|
||||
- EVAL
|
||||
- value:
|
||||
name: "contextrelevant"
|
||||
value: "not relevant"
|
||||
sessionId: "abyt-1234-5678-80ab"
|
||||
- value:
|
||||
name: "hallucination"
|
||||
value: 0
|
||||
datasetRunId: "7891-5678-90ab-hijk"
|
||||
|
||||
ScoreDataType:
|
||||
enum:
|
||||
- NUMERIC
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
name: langfuse-organizations
|
||||
docs: |
|
||||
## General Notes
|
||||
|
||||
This admin API is only available on self-hosted instances, not on Langfuse Cloud.
|
||||
An administrator must set the `ADMIN_API_KEY` environment variable to use this API.
|
||||
|
||||
## Authentication
|
||||
|
||||
Authenticate with the API by setting the Authorization header to `Bearer $ADMIN_API_KEY` where
|
||||
`$ADMIN_API_KEY` is the API key set via the container environment.
|
||||
|
||||
## Exports
|
||||
|
||||
- OpenAPI spec: https://cloud.langfuse.com/generated/organizations-api/openapi.yml
|
||||
- Postman collection: https://cloud.langfuse.com/generated/organizations-postman/collection.json
|
||||
|
||||
## Looking for the Langfuse API?
|
||||
|
||||
Are you looking for the full Langfuse API?
|
||||
Check out our [API reference](https://api.reference.langfuse.com/#overview).
|
||||
|
||||
error-discrimination:
|
||||
strategy: status-code
|
||||
auth: bearer
|
||||
imports:
|
||||
commons: commons.yml
|
||||
errors:
|
||||
- commons.Error
|
||||
- commons.UnauthorizedError
|
||||
- commons.AccessDeniedError
|
||||
- commons.MethodNotAllowedError
|
||||
@@ -0,0 +1,13 @@
|
||||
errors:
|
||||
Error:
|
||||
status-code: 400
|
||||
type: string
|
||||
UnauthorizedError:
|
||||
status-code: 401
|
||||
type: string
|
||||
AccessDeniedError:
|
||||
status-code: 403
|
||||
type: string
|
||||
MethodNotAllowedError:
|
||||
status-code: 405
|
||||
type: string
|
||||
@@ -0,0 +1,170 @@
|
||||
# yaml-language-server: $schema=https://raw.githubusercontent.com/fern-api/fern/main/fern.schema.json
|
||||
imports:
|
||||
commons: ./commons.yml
|
||||
|
||||
service:
|
||||
auth: true
|
||||
base-path: /api/admin
|
||||
endpoints:
|
||||
getAll:
|
||||
docs: Get all organizations
|
||||
method: GET
|
||||
path: /organizations
|
||||
response: Organizations
|
||||
errors:
|
||||
- commons.UnauthorizedError
|
||||
- commons.MethodNotAllowedError
|
||||
|
||||
create:
|
||||
docs: Create a new organization
|
||||
method: POST
|
||||
path: /organizations
|
||||
request:
|
||||
name: CreateOrganizationRequest
|
||||
body:
|
||||
properties:
|
||||
name: string
|
||||
metadata:
|
||||
type: optional<map<string, unknown>>
|
||||
docs: Optional metadata for the organization
|
||||
response: Organization
|
||||
errors:
|
||||
- commons.Error
|
||||
- commons.UnauthorizedError
|
||||
- commons.MethodNotAllowedError
|
||||
|
||||
getById:
|
||||
docs: Get organization by ID
|
||||
method: GET
|
||||
path: /organizations/{organizationId}
|
||||
path-parameters:
|
||||
organizationId: string
|
||||
response: Organization
|
||||
errors:
|
||||
- commons.Error
|
||||
- commons.UnauthorizedError
|
||||
- commons.MethodNotAllowedError
|
||||
|
||||
update:
|
||||
docs: Update an organization
|
||||
method: PUT
|
||||
path: /organizations/{organizationId}
|
||||
path-parameters:
|
||||
organizationId: string
|
||||
request:
|
||||
name: UpdateOrganizationRequest
|
||||
body:
|
||||
properties:
|
||||
name: string
|
||||
metadata:
|
||||
type: optional<map<string, unknown>>
|
||||
docs: Optional metadata for the organization
|
||||
response: Organization
|
||||
errors:
|
||||
- commons.Error
|
||||
- commons.UnauthorizedError
|
||||
- commons.MethodNotAllowedError
|
||||
|
||||
delete:
|
||||
docs: Delete an organization
|
||||
method: DELETE
|
||||
path: /organizations/{organizationId}
|
||||
path-parameters:
|
||||
organizationId: string
|
||||
response: DeleteOrganizationResponse
|
||||
errors:
|
||||
- commons.Error
|
||||
- commons.UnauthorizedError
|
||||
- commons.MethodNotAllowedError
|
||||
|
||||
# API Key endpoints
|
||||
getApiKeys:
|
||||
docs: Get all API keys for an organization
|
||||
method: GET
|
||||
path: /organizations/{organizationId}/apiKeys
|
||||
path-parameters:
|
||||
organizationId: string
|
||||
response: ApiKeyList
|
||||
errors:
|
||||
- commons.Error
|
||||
- commons.UnauthorizedError
|
||||
- commons.MethodNotAllowedError
|
||||
|
||||
createApiKey:
|
||||
docs: Create a new API key for an organization
|
||||
method: POST
|
||||
path: /organizations/{organizationId}/apiKeys
|
||||
path-parameters:
|
||||
organizationId: string
|
||||
request:
|
||||
name: CreateApiKeyRequest
|
||||
body:
|
||||
properties:
|
||||
note:
|
||||
type: optional<string>
|
||||
docs: Optional note for the API key
|
||||
response: ApiKeyResponse
|
||||
errors:
|
||||
- commons.Error
|
||||
- commons.UnauthorizedError
|
||||
- commons.MethodNotAllowedError
|
||||
|
||||
deleteApiKey:
|
||||
docs: Delete an API key for an organization
|
||||
method: DELETE
|
||||
path: /organizations/{organizationId}/apiKeys/{apiKeyId}
|
||||
path-parameters:
|
||||
organizationId: string
|
||||
apiKeyId: string
|
||||
response: DeleteOrganizationResponse
|
||||
errors:
|
||||
- commons.Error
|
||||
- commons.UnauthorizedError
|
||||
- commons.MethodNotAllowedError
|
||||
|
||||
types:
|
||||
Organizations:
|
||||
docs: List of organizations
|
||||
properties:
|
||||
organizations: list<Organization>
|
||||
|
||||
Organization:
|
||||
docs: Organization object
|
||||
properties:
|
||||
id: string
|
||||
name: string
|
||||
createdAt: datetime
|
||||
metadata:
|
||||
type: map<string, unknown>
|
||||
docs: Metadata for the organization
|
||||
|
||||
DeleteOrganizationResponse:
|
||||
docs: Response for successful organization deletion
|
||||
properties:
|
||||
success: boolean
|
||||
|
||||
ApiKeyList:
|
||||
docs: List of API keys for an organization
|
||||
properties:
|
||||
apiKeys: list<ApiKeySummary>
|
||||
|
||||
ApiKeySummary:
|
||||
docs: Summary of an API key
|
||||
properties:
|
||||
id: string
|
||||
createdAt: datetime
|
||||
expiresAt: optional<datetime>
|
||||
lastUsedAt: optional<datetime>
|
||||
note: optional<string>
|
||||
publicKey: string
|
||||
displaySecretKey: string
|
||||
|
||||
ApiKeyResponse:
|
||||
docs: Response for API key creation
|
||||
properties:
|
||||
id: string
|
||||
createdAt: datetime
|
||||
publicKey: string
|
||||
secretKey: string
|
||||
displaySecretKey: string
|
||||
note: optional<string>
|
||||
@@ -0,0 +1,17 @@
|
||||
default-group: local
|
||||
groups:
|
||||
local:
|
||||
generators:
|
||||
- name: fernapi/fern-openapi
|
||||
version: 0.1.7
|
||||
output:
|
||||
location: local-file-system
|
||||
path: ../../../web/public/generated/organizations-api
|
||||
config:
|
||||
namespaceExport: Langfuse
|
||||
allowCustomFetcher: true
|
||||
- name: fernapi/fern-postman
|
||||
version: 0.0.45
|
||||
output:
|
||||
location: local-file-system
|
||||
path: ../../../web/public/generated/organizations-postman
|
||||
@@ -0,0 +1,165 @@
|
||||
# yaml-language-server: $schema=https://raw.githubusercontent.com/fern-api/fern/main/fern.schema.json
|
||||
imports:
|
||||
commons: ./commons.yml
|
||||
pagination: ./utils/pagination.yml
|
||||
|
||||
service:
|
||||
auth: true
|
||||
base-path: /api/public
|
||||
endpoints:
|
||||
listQueues:
|
||||
docs: Get all annotation queues
|
||||
method: GET
|
||||
path: /annotation-queues
|
||||
request:
|
||||
name: GetAnnotationQueuesRequest
|
||||
query-parameters:
|
||||
page:
|
||||
type: optional<integer>
|
||||
docs: page number, starts at 1
|
||||
limit:
|
||||
type: optional<integer>
|
||||
docs: limit of items per page
|
||||
response: PaginatedAnnotationQueues
|
||||
|
||||
getQueue:
|
||||
docs: Get an annotation queue by ID
|
||||
method: GET
|
||||
path: /annotation-queues/{queueId}
|
||||
path-parameters:
|
||||
queueId:
|
||||
type: string
|
||||
docs: The unique identifier of the annotation queue
|
||||
response: AnnotationQueue
|
||||
|
||||
listQueueItems:
|
||||
docs: Get items for a specific annotation queue
|
||||
method: GET
|
||||
path: /annotation-queues/{queueId}/items
|
||||
path-parameters:
|
||||
queueId:
|
||||
type: string
|
||||
docs: The unique identifier of the annotation queue
|
||||
request:
|
||||
name: GetAnnotationQueueItemsRequest
|
||||
query-parameters:
|
||||
status:
|
||||
type: optional<AnnotationQueueStatus>
|
||||
docs: Filter by status
|
||||
page:
|
||||
type: optional<integer>
|
||||
docs: page number, starts at 1
|
||||
limit:
|
||||
type: optional<integer>
|
||||
docs: limit of items per page
|
||||
response: PaginatedAnnotationQueueItems
|
||||
|
||||
getQueueItem:
|
||||
docs: Get a specific item from an annotation queue
|
||||
method: GET
|
||||
path: /annotation-queues/{queueId}/items/{itemId}
|
||||
path-parameters:
|
||||
queueId:
|
||||
type: string
|
||||
docs: The unique identifier of the annotation queue
|
||||
itemId:
|
||||
type: string
|
||||
docs: The unique identifier of the annotation queue item
|
||||
response: AnnotationQueueItem
|
||||
|
||||
createQueueItem:
|
||||
docs: Add an item to an annotation queue
|
||||
method: POST
|
||||
path: /annotation-queues/{queueId}/items
|
||||
path-parameters:
|
||||
queueId:
|
||||
type: string
|
||||
docs: The unique identifier of the annotation queue
|
||||
request: CreateAnnotationQueueItemRequest
|
||||
response: AnnotationQueueItem
|
||||
|
||||
updateQueueItem:
|
||||
docs: Update an annotation queue item
|
||||
method: PATCH
|
||||
path: /annotation-queues/{queueId}/items/{itemId}
|
||||
path-parameters:
|
||||
queueId:
|
||||
type: string
|
||||
docs: The unique identifier of the annotation queue
|
||||
itemId:
|
||||
type: string
|
||||
docs: The unique identifier of the annotation queue item
|
||||
request: UpdateAnnotationQueueItemRequest
|
||||
response: AnnotationQueueItem
|
||||
|
||||
deleteQueueItem:
|
||||
docs: Remove an item from an annotation queue
|
||||
method: DELETE
|
||||
path: /annotation-queues/{queueId}/items/{itemId}
|
||||
path-parameters:
|
||||
queueId:
|
||||
type: string
|
||||
docs: The unique identifier of the annotation queue
|
||||
itemId:
|
||||
type: string
|
||||
docs: The unique identifier of the annotation queue item
|
||||
response: DeleteAnnotationQueueItemResponse
|
||||
|
||||
types:
|
||||
AnnotationQueueStatus:
|
||||
enum:
|
||||
- PENDING
|
||||
- COMPLETED
|
||||
|
||||
AnnotationQueueObjectType:
|
||||
enum:
|
||||
- TRACE
|
||||
- OBSERVATION
|
||||
|
||||
AnnotationQueue:
|
||||
properties:
|
||||
id: string
|
||||
name: string
|
||||
description: optional<string>
|
||||
scoreConfigIds: list<string>
|
||||
createdAt: datetime
|
||||
updatedAt: datetime
|
||||
|
||||
AnnotationQueueItem:
|
||||
properties:
|
||||
id: string
|
||||
queueId: string
|
||||
objectId: string
|
||||
objectType: AnnotationQueueObjectType
|
||||
status: AnnotationQueueStatus
|
||||
completedAt: optional<datetime>
|
||||
createdAt: datetime
|
||||
updatedAt: datetime
|
||||
|
||||
PaginatedAnnotationQueues:
|
||||
properties:
|
||||
data: list<AnnotationQueue>
|
||||
meta: pagination.MetaResponse
|
||||
|
||||
PaginatedAnnotationQueueItems:
|
||||
properties:
|
||||
data: list<AnnotationQueueItem>
|
||||
meta: pagination.MetaResponse
|
||||
|
||||
CreateAnnotationQueueItemRequest:
|
||||
properties:
|
||||
objectId: string
|
||||
objectType: AnnotationQueueObjectType
|
||||
status:
|
||||
type: optional<AnnotationQueueStatus>
|
||||
docs: Defaults to PENDING for new queue items
|
||||
|
||||
UpdateAnnotationQueueItemRequest:
|
||||
properties:
|
||||
status:
|
||||
type: optional<AnnotationQueueStatus>
|
||||
|
||||
DeleteAnnotationQueueItemResponse:
|
||||
properties:
|
||||
success: boolean
|
||||
message: string
|
||||
@@ -75,7 +75,7 @@ types:
|
||||
type: list<ObservationsView>
|
||||
docs: List of observations
|
||||
scores:
|
||||
type: list<Score>
|
||||
type: list<ScoreV1>
|
||||
docs: List of scores
|
||||
Session:
|
||||
properties:
|
||||
@@ -240,7 +240,7 @@ types:
|
||||
properties:
|
||||
value: double
|
||||
label: string
|
||||
BaseScore:
|
||||
BaseScoreV1:
|
||||
properties:
|
||||
id: string
|
||||
traceId: string
|
||||
@@ -252,6 +252,68 @@ types:
|
||||
updatedAt: datetime
|
||||
authorUserId: optional<string>
|
||||
comment: optional<string>
|
||||
metadata: optional<unknown>
|
||||
configId:
|
||||
type: optional<string>
|
||||
docs: Reference a score config on a score. When set, config and score name must be equal and value must comply to optionally defined numerical range
|
||||
queueId:
|
||||
type: optional<string>
|
||||
docs: Reference an annotation queue on a score. Populated if the score was initially created in an annotation queue.
|
||||
environment:
|
||||
type: optional<string>
|
||||
docs: The environment from which this score originated. Can be any lowercase alphanumeric string with hyphens and underscores that does not start with 'langfuse'.
|
||||
NumericScoreV1:
|
||||
extends: BaseScoreV1
|
||||
properties:
|
||||
value:
|
||||
type: double
|
||||
docs: The numeric value of the score
|
||||
BooleanScoreV1:
|
||||
extends: BaseScoreV1
|
||||
properties:
|
||||
value:
|
||||
type: double
|
||||
docs: The numeric value of the score. Equals 1 for "True" and 0 for "False"
|
||||
stringValue:
|
||||
type: string
|
||||
docs: The string representation of the score value. Is inferred from the numeric value and equals "True" or "False"
|
||||
CategoricalScoreV1:
|
||||
extends: BaseScoreV1
|
||||
properties:
|
||||
value:
|
||||
type: optional<double>
|
||||
docs: Only defined if a config is linked. Represents the numeric category mapping of the stringValue
|
||||
stringValue:
|
||||
type: string
|
||||
docs: The string representation of the score value. If no config is linked, can be any string. Otherwise, must map to a config category
|
||||
ScoreV1:
|
||||
discriminant: "dataType"
|
||||
union:
|
||||
NUMERIC:
|
||||
type: NumericScoreV1
|
||||
docs: "Score with NUMERIC data type"
|
||||
CATEGORICAL:
|
||||
type: CategoricalScoreV1
|
||||
docs: "Score with CATEGORICAL data type"
|
||||
BOOLEAN:
|
||||
type: BooleanScoreV1
|
||||
docs: "Score with BOOLEAN data type"
|
||||
|
||||
BaseScore:
|
||||
properties:
|
||||
id: string
|
||||
traceId: optional<string>
|
||||
sessionId: optional<string>
|
||||
observationId: optional<string>
|
||||
datasetRunId: optional<string>
|
||||
name: string
|
||||
source: ScoreSource
|
||||
timestamp: datetime
|
||||
createdAt: datetime
|
||||
updatedAt: datetime
|
||||
authorUserId: optional<string>
|
||||
comment: optional<string>
|
||||
metadata: optional<unknown>
|
||||
configId:
|
||||
type: optional<string>
|
||||
docs: Reference a score config on a score. When set, config and score name must be equal and value must comply to optionally defined numerical range
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# yaml-language-server: $schema=https://raw.githubusercontent.com/fern-api/fern/main/fern.schema.json
|
||||
imports:
|
||||
commons: ./commons.yml
|
||||
pagination: ./utils/pagination.yml
|
||||
service:
|
||||
auth: true
|
||||
base-path: /api/public
|
||||
@@ -11,6 +12,23 @@ service:
|
||||
path: /dataset-run-items
|
||||
request: CreateDatasetRunItemRequest
|
||||
response: commons.DatasetRunItem
|
||||
list:
|
||||
method: GET
|
||||
docs: List dataset run items
|
||||
path: /dataset-run-items
|
||||
request:
|
||||
name: ListDatasetRunItemsRequest
|
||||
query-parameters:
|
||||
datasetId: string
|
||||
runName: string
|
||||
page:
|
||||
type: optional<integer>
|
||||
docs: page number, starts at 1
|
||||
limit:
|
||||
type: optional<integer>
|
||||
docs: limit of items per page
|
||||
response: PaginatedDatasetRunItems
|
||||
|
||||
types:
|
||||
CreateDatasetRunItemRequest:
|
||||
properties:
|
||||
@@ -26,3 +44,7 @@ types:
|
||||
traceId:
|
||||
type: optional<string>
|
||||
docs: traceId should always be provided. For compatibility with older SDK versions it can also be inferred from the provided observationId.
|
||||
PaginatedDatasetRunItems:
|
||||
properties:
|
||||
data: list<commons.DatasetRunItem>
|
||||
meta: pagination.MetaResponse
|
||||
|
||||
@@ -263,14 +263,17 @@ types:
|
||||
ScoreBody:
|
||||
properties:
|
||||
id: optional<string>
|
||||
traceId: string
|
||||
traceId: optional<string>
|
||||
sessionId: optional<string>
|
||||
observationId: optional<string>
|
||||
datasetRunId: optional<string>
|
||||
name: string
|
||||
environment: optional<string>
|
||||
value:
|
||||
type: commons.CreateScoreValue
|
||||
docs: The value of the score. Must be passed as string for categorical scores, and numeric for boolean and numeric scores. Boolean score values must equal either 1 or 0 (true or false)
|
||||
observationId: optional<string>
|
||||
comment: optional<string>
|
||||
metadata: optional<unknown>
|
||||
dataType:
|
||||
type: optional<commons.ScoreDataType>
|
||||
docs: When set, must match the score value's type. If not set, will be inferred from the score value or config
|
||||
@@ -314,6 +317,14 @@ types:
|
||||
dataType: "BOOLEAN"
|
||||
configId: "1234-5678-90ab-cdef"
|
||||
traceId: "cdef-1234-5678-90ab"
|
||||
- value:
|
||||
name: "contextrelevant"
|
||||
value: "not relevant"
|
||||
sessionId: "abyt-1234-5678-80ab"
|
||||
- value:
|
||||
name: "hallucination"
|
||||
value: 0
|
||||
datasetRunId: "7891-5678-90ab-hijk"
|
||||
|
||||
BaseEvent:
|
||||
properties:
|
||||
@@ -394,16 +405,27 @@ types:
|
||||
successes: list<IngestionSuccess>
|
||||
errors: list<IngestionError>
|
||||
|
||||
OpenAIUsageSchema:
|
||||
OpenAICompletionUsageSchema:
|
||||
docs: OpenAI Usage schema from (Chat-)Completion APIs
|
||||
properties:
|
||||
prompt_tokens: integer
|
||||
completion_tokens: integer
|
||||
total_tokens: integer
|
||||
prompt_tokens_details: optional<map<string, integer>>
|
||||
completion_tokens_details: optional<map<string, integer>>
|
||||
prompt_tokens_details: optional<map<string, optional<integer>>>
|
||||
completion_tokens_details: optional<map<string, optional<integer>>>
|
||||
|
||||
OpenAIResponseUsageSchema:
|
||||
docs: OpenAI Usage schema from Response API
|
||||
properties:
|
||||
input_tokens: integer
|
||||
output_tokens: integer
|
||||
total_tokens: integer
|
||||
input_tokens_details: optional<map<string, optional<integer>>>
|
||||
output_tokens_details: optional<map<string, optional<integer>>>
|
||||
|
||||
UsageDetails:
|
||||
discriminated: false
|
||||
union:
|
||||
- map<string, integer>
|
||||
- OpenAIUsageSchema
|
||||
- OpenAICompletionUsageSchema
|
||||
- OpenAIResponseUsageSchema
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
# yaml-language-server: $schema=https://raw.githubusercontent.com/fern-api/fern/main/fern.schema.json
|
||||
imports:
|
||||
commons: ./commons.yml
|
||||
pagination: ./utils/pagination.yml
|
||||
|
||||
service:
|
||||
auth: true
|
||||
base-path: /api/public
|
||||
endpoints:
|
||||
getOrganizationMemberships:
|
||||
docs: Get all memberships for the organization associated with the API key (requires organization-scoped API key)
|
||||
method: GET
|
||||
path: /organizations/memberships
|
||||
response: MembershipsResponse
|
||||
|
||||
updateOrganizationMembership:
|
||||
docs: Create or update a membership for the organization associated with the API key (requires organization-scoped API key)
|
||||
method: PUT
|
||||
path: /organizations/memberships
|
||||
request: MembershipRequest
|
||||
response: MembershipResponse
|
||||
|
||||
getProjectMemberships:
|
||||
docs: Get all memberships for a specific project (requires organization-scoped API key)
|
||||
method: GET
|
||||
path: /projects/{projectId}/memberships
|
||||
path-parameters:
|
||||
projectId: string
|
||||
response: MembershipsResponse
|
||||
|
||||
updateProjectMembership:
|
||||
docs: Create or update a membership for a specific project (requires organization-scoped API key). The user must already be a member of the organization.
|
||||
method: PUT
|
||||
path: /projects/{projectId}/memberships
|
||||
path-parameters:
|
||||
projectId: string
|
||||
request: MembershipRequest
|
||||
response: MembershipResponse
|
||||
|
||||
types:
|
||||
MembershipRole:
|
||||
enum:
|
||||
- OWNER
|
||||
- ADMIN
|
||||
- MEMBER
|
||||
- VIEWER
|
||||
|
||||
MembershipRequest:
|
||||
properties:
|
||||
userId: string
|
||||
role: MembershipRole
|
||||
|
||||
MembershipResponse:
|
||||
properties:
|
||||
userId: string
|
||||
role: MembershipRole
|
||||
email: string
|
||||
name: string
|
||||
|
||||
MembershipsResponse:
|
||||
properties:
|
||||
memberships: list<MembershipResponse>
|
||||
@@ -6,6 +6,54 @@ service:
|
||||
auth: true
|
||||
base-path: /api/public
|
||||
endpoints:
|
||||
metrics:
|
||||
docs: Get metrics from the Langfuse project using a query object
|
||||
method: GET
|
||||
path: /metrics
|
||||
request:
|
||||
name: GetMetricsRequest
|
||||
query-parameters:
|
||||
query:
|
||||
type: string
|
||||
docs: |
|
||||
JSON string containing the query parameters with the following structure:
|
||||
```json
|
||||
{
|
||||
"view": string, // Required. One of "traces", "observations", "scores-numeric", "scores-categorical"
|
||||
"dimensions": [ // Optional. Default: []
|
||||
{
|
||||
"field": string // Field to group by, e.g. "name", "userId", "sessionId"
|
||||
}
|
||||
],
|
||||
"metrics": [ // Required. At least one metric must be provided
|
||||
{
|
||||
"measure": string, // What to measure, e.g. "count", "latency", "value"
|
||||
"aggregation": string // How to aggregate, e.g. "count", "sum", "avg", "p95"
|
||||
}
|
||||
],
|
||||
"filters": [ // Optional. Default: []
|
||||
{
|
||||
"column": string, // Column to filter on
|
||||
"operator": string, // Operator, e.g. "=", ">", "<", "contains"
|
||||
"value": any, // Value to compare against
|
||||
"type": string, // Data type, e.g. "string", "number", "stringObject"
|
||||
"key": string // Required only when filtering on metadata
|
||||
}
|
||||
],
|
||||
"timeDimension": { // Optional. Default: null. If provided, results will be grouped by time
|
||||
"granularity": string // One of "minute", "hour", "day", "week", "month", "auto"
|
||||
},
|
||||
"fromTimestamp": string, // Required. ISO datetime string for start of time range
|
||||
"toTimestamp": string, // Required. ISO datetime string for end of time range
|
||||
"orderBy": [ // Optional. Default: null
|
||||
{
|
||||
"field": string, // Field to order by
|
||||
"direction": string // "asc" or "desc"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
response: MetricsResponse
|
||||
daily:
|
||||
docs: Get daily metrics of the Langfuse project
|
||||
method: GET
|
||||
@@ -41,6 +89,13 @@ service:
|
||||
docs: Optional filter to only include traces and observations before a certain datetime (ISO 8601)
|
||||
response: DailyMetrics
|
||||
types:
|
||||
MetricsResponse:
|
||||
properties:
|
||||
data:
|
||||
type: list<map<string, unknown>>
|
||||
docs: |
|
||||
The metrics data. Each item in the list contains the metric values and dimensions requested in the query.
|
||||
Format varies based on the query parameters.
|
||||
DailyMetrics:
|
||||
properties:
|
||||
data:
|
||||
|
||||
@@ -11,6 +11,85 @@ service:
|
||||
method: GET
|
||||
path: /projects
|
||||
response: Projects
|
||||
|
||||
create:
|
||||
docs: Create a new project (requires organization-scoped API key)
|
||||
method: POST
|
||||
path: /projects
|
||||
request:
|
||||
name: CreateProjectRequest
|
||||
body:
|
||||
properties:
|
||||
name: string
|
||||
metadata:
|
||||
type: optional<map<string, unknown>>
|
||||
docs: Optional metadata for the project
|
||||
retention:
|
||||
type: integer
|
||||
docs: Number of days to retain data. Must be 0 or at least 7 days. Requires data-retention entitlement for non-zero values. Optional.
|
||||
response: Project
|
||||
|
||||
update:
|
||||
docs: Update a project by ID (requires organization-scoped API key).
|
||||
method: PUT
|
||||
path: /projects/{projectId}
|
||||
path-parameters:
|
||||
projectId: string
|
||||
request:
|
||||
name: UpdateProjectRequest
|
||||
body:
|
||||
properties:
|
||||
name: string
|
||||
metadata:
|
||||
type: optional<map<string, unknown>>
|
||||
docs: Optional metadata for the project
|
||||
retention:
|
||||
type: integer
|
||||
docs: Number of days to retain data. Must be 0 or at least 7 days. Requires data-retention entitlement for non-zero values. Optional.
|
||||
response: Project
|
||||
|
||||
delete:
|
||||
docs: Delete a project by ID (requires organization-scoped API key). Project deletion is processed asynchronously.
|
||||
method: DELETE
|
||||
path: /projects/{projectId}
|
||||
path-parameters:
|
||||
projectId: string
|
||||
response:
|
||||
status-code: 202
|
||||
type: ProjectDeletionResponse
|
||||
|
||||
# API Key endpoints
|
||||
getApiKeys:
|
||||
docs: Get all API keys for a project (requires organization-scoped API key)
|
||||
method: GET
|
||||
path: /projects/{projectId}/apiKeys
|
||||
path-parameters:
|
||||
projectId: string
|
||||
response: ApiKeyList
|
||||
|
||||
createApiKey:
|
||||
docs: Create a new API key for a project (requires organization-scoped API key)
|
||||
method: POST
|
||||
path: /projects/{projectId}/apiKeys
|
||||
path-parameters:
|
||||
projectId: string
|
||||
request:
|
||||
name: CreateApiKeyRequest
|
||||
body:
|
||||
properties:
|
||||
note:
|
||||
type: optional<string>
|
||||
docs: Optional note for the API key
|
||||
response: ApiKeyResponse
|
||||
|
||||
deleteApiKey:
|
||||
docs: Delete an API key for a project (requires organization-scoped API key)
|
||||
method: DELETE
|
||||
path: /projects/{projectId}/apiKeys/{apiKeyId}
|
||||
path-parameters:
|
||||
projectId: string
|
||||
apiKeyId: string
|
||||
response: ApiKeyDeletionResponse
|
||||
|
||||
types:
|
||||
Projects:
|
||||
@@ -21,3 +100,45 @@ types:
|
||||
properties:
|
||||
id: string
|
||||
name: string
|
||||
metadata:
|
||||
type: map<string, unknown>
|
||||
docs: Metadata for the project
|
||||
retentionDays:
|
||||
type: integer
|
||||
docs: Number of days to retain data. Null or 0 means no retention. Omitted if no retention is configured.
|
||||
|
||||
ProjectDeletionResponse:
|
||||
properties:
|
||||
success: boolean
|
||||
message: string
|
||||
|
||||
ApiKeyList:
|
||||
docs: List of API keys for a project
|
||||
properties:
|
||||
apiKeys: list<ApiKeySummary>
|
||||
|
||||
ApiKeySummary:
|
||||
docs: Summary of an API key
|
||||
properties:
|
||||
id: string
|
||||
createdAt: datetime
|
||||
expiresAt: optional<datetime>
|
||||
lastUsedAt: optional<datetime>
|
||||
note: optional<string>
|
||||
publicKey: string
|
||||
displaySecretKey: string
|
||||
|
||||
ApiKeyResponse:
|
||||
docs: Response for API key creation
|
||||
properties:
|
||||
id: string
|
||||
createdAt: datetime
|
||||
publicKey: string
|
||||
secretKey: string
|
||||
displaySecretKey: string
|
||||
note: optional<string>
|
||||
|
||||
ApiKeyDeletionResponse:
|
||||
docs: Response for API key deletion
|
||||
properties:
|
||||
success: boolean
|
||||
|
||||
@@ -128,6 +128,9 @@ types:
|
||||
commitMessage:
|
||||
type: optional<string>
|
||||
docs: Commit message for this prompt version.
|
||||
resolutionGraph:
|
||||
type: optional<map<string, unknown>>
|
||||
docs: The dependency resolution graph for the current prompt. Null if prompt has no dependencies.
|
||||
|
||||
ChatMessage:
|
||||
properties:
|
||||
|
||||
@@ -0,0 +1,199 @@
|
||||
# yaml-language-server: $schema=https://raw.githubusercontent.com/fern-api/fern/main/fern.schema.json
|
||||
imports:
|
||||
commons: ./commons.yml
|
||||
|
||||
service:
|
||||
auth: true
|
||||
base-path: /api/public/scim
|
||||
endpoints:
|
||||
getServiceProviderConfig:
|
||||
docs: Get SCIM Service Provider Configuration (requires organization-scoped API key)
|
||||
method: GET
|
||||
path: /ServiceProviderConfig
|
||||
response: ServiceProviderConfig
|
||||
|
||||
getResourceTypes:
|
||||
docs: Get SCIM Resource Types (requires organization-scoped API key)
|
||||
method: GET
|
||||
path: /ResourceTypes
|
||||
response: ResourceTypesResponse
|
||||
|
||||
getSchemas:
|
||||
docs: Get SCIM Schemas (requires organization-scoped API key)
|
||||
method: GET
|
||||
path: /Schemas
|
||||
response: SchemasResponse
|
||||
|
||||
listUsers:
|
||||
docs: List users in the organization (requires organization-scoped API key)
|
||||
method: GET
|
||||
path: /Users
|
||||
request:
|
||||
name: ListUsersRequest
|
||||
query-parameters:
|
||||
filter:
|
||||
docs: Filter expression (e.g. userName eq "value")
|
||||
type: optional<string>
|
||||
startIndex:
|
||||
docs: 1-based index of the first result to return (default 1)
|
||||
type: optional<integer>
|
||||
count:
|
||||
docs: Maximum number of results to return (default 100)
|
||||
type: optional<integer>
|
||||
response: ScimUsersListResponse
|
||||
|
||||
createUser:
|
||||
docs: Create a new user in the organization (requires organization-scoped API key)
|
||||
method: POST
|
||||
path: /Users
|
||||
request:
|
||||
name: CreateUserRequest
|
||||
body:
|
||||
properties:
|
||||
userName:
|
||||
docs: User's email address (required)
|
||||
type: string
|
||||
name:
|
||||
docs: User's name information
|
||||
type: ScimName
|
||||
emails:
|
||||
docs: User's email addresses
|
||||
type: optional<list<ScimEmail>>
|
||||
active:
|
||||
docs: Whether the user is active
|
||||
type: optional<boolean>
|
||||
password:
|
||||
docs: Initial password for the user
|
||||
type: optional<string>
|
||||
response: ScimUser
|
||||
|
||||
getUser:
|
||||
docs: Get a specific user by ID (requires organization-scoped API key)
|
||||
method: GET
|
||||
path: /Users/{userId}
|
||||
path-parameters:
|
||||
userId: string
|
||||
response: ScimUser
|
||||
|
||||
deleteUser:
|
||||
docs: Remove a user from the organization (requires organization-scoped API key). Note that this only removes the user from the organization but does not delete the user entity itself.
|
||||
method: DELETE
|
||||
path: /Users/{userId}
|
||||
path-parameters:
|
||||
userId: string
|
||||
response: EmptyResponse
|
||||
|
||||
types:
|
||||
ServiceProviderConfig:
|
||||
properties:
|
||||
schemas: list<string>
|
||||
documentationUri: string
|
||||
patch: ScimFeatureSupport
|
||||
bulk: BulkConfig
|
||||
filter: FilterConfig
|
||||
changePassword: ScimFeatureSupport
|
||||
sort: ScimFeatureSupport
|
||||
etag: ScimFeatureSupport
|
||||
authenticationSchemes: list<AuthenticationScheme>
|
||||
meta: ResourceMeta
|
||||
|
||||
ScimFeatureSupport:
|
||||
properties:
|
||||
supported: boolean
|
||||
|
||||
BulkConfig:
|
||||
properties:
|
||||
supported: boolean
|
||||
maxOperations: integer
|
||||
maxPayloadSize: integer
|
||||
|
||||
FilterConfig:
|
||||
properties:
|
||||
supported: boolean
|
||||
maxResults: integer
|
||||
|
||||
ResourceMeta:
|
||||
properties:
|
||||
resourceType: string
|
||||
location: string
|
||||
|
||||
AuthenticationScheme:
|
||||
properties:
|
||||
name: string
|
||||
description: string
|
||||
specUri: string
|
||||
type: string
|
||||
primary: boolean
|
||||
|
||||
ResourceTypesResponse:
|
||||
properties:
|
||||
schemas: list<string>
|
||||
totalResults: integer
|
||||
Resources: list<ResourceType>
|
||||
|
||||
ResourceType:
|
||||
properties:
|
||||
schemas: optional<list<string>>
|
||||
id: string
|
||||
name: string
|
||||
endpoint: string
|
||||
description: string
|
||||
schema: string
|
||||
schemaExtensions: list<SchemaExtension>
|
||||
meta: ResourceMeta
|
||||
|
||||
SchemaExtension:
|
||||
properties:
|
||||
schema: string
|
||||
required: boolean
|
||||
|
||||
SchemasResponse:
|
||||
properties:
|
||||
schemas: list<string>
|
||||
totalResults: integer
|
||||
Resources: list<SchemaResource>
|
||||
|
||||
SchemaResource:
|
||||
properties:
|
||||
id: string
|
||||
name: string
|
||||
description: string
|
||||
attributes: list<unknown>
|
||||
meta: ResourceMeta
|
||||
|
||||
ScimUsersListResponse:
|
||||
properties:
|
||||
schemas: list<string>
|
||||
totalResults: integer
|
||||
startIndex: integer
|
||||
itemsPerPage: integer
|
||||
Resources: list<ScimUser>
|
||||
|
||||
ScimUser:
|
||||
properties:
|
||||
schemas: list<string>
|
||||
id: string
|
||||
userName: string
|
||||
name: ScimName
|
||||
emails: list<ScimEmail>
|
||||
meta: UserMeta
|
||||
|
||||
UserMeta:
|
||||
properties:
|
||||
resourceType: string
|
||||
created: optional<string>
|
||||
lastModified: optional<string>
|
||||
|
||||
ScimName:
|
||||
properties:
|
||||
formatted: optional<string>
|
||||
|
||||
ScimEmail:
|
||||
properties:
|
||||
primary: boolean
|
||||
value: string
|
||||
type: string
|
||||
|
||||
EmptyResponse:
|
||||
docs: Empty response for 204 No Content responses
|
||||
properties: {}
|
||||
@@ -0,0 +1,112 @@
|
||||
# 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/v2
|
||||
endpoints:
|
||||
get:
|
||||
docs: Get a list of scores (supports both trace and session scores)
|
||||
method: GET
|
||||
path: /scores
|
||||
request:
|
||||
name: GetScoresRequest
|
||||
query-parameters:
|
||||
page:
|
||||
type: optional<integer>
|
||||
docs: Page number, starts at 1.
|
||||
limit:
|
||||
type: optional<integer>
|
||||
docs: Limit of items per page. If you encounter api issues due to too large page sizes, try to reduce the limit.
|
||||
userId:
|
||||
type: optional<string>
|
||||
docs: Retrieve only scores with this userId associated to the trace.
|
||||
name:
|
||||
type: optional<string>
|
||||
docs: Retrieve only scores with this name.
|
||||
fromTimestamp:
|
||||
type: optional<datetime>
|
||||
docs: Optional filter to only include scores created on or after a certain datetime (ISO 8601)
|
||||
toTimestamp:
|
||||
type: optional<datetime>
|
||||
docs: Optional filter to only include scores created before a certain datetime (ISO 8601)
|
||||
environment:
|
||||
type: optional<string>
|
||||
allow-multiple: true
|
||||
docs: Optional filter for scores where the environment is one of the provided values.
|
||||
source:
|
||||
type: optional<commons.ScoreSource>
|
||||
docs: Retrieve only scores from a specific source.
|
||||
operator:
|
||||
type: optional<string>
|
||||
docs: Retrieve only scores with <operator> value.
|
||||
value:
|
||||
type: optional<double>
|
||||
docs: Retrieve only scores with <operator> value.
|
||||
scoreIds:
|
||||
type: optional<string>
|
||||
docs: Comma-separated list of score IDs to limit the results to.
|
||||
configId:
|
||||
type: optional<string>
|
||||
docs: Retrieve only scores with a specific configId.
|
||||
queueId:
|
||||
type: optional<string>
|
||||
docs: Retrieve only scores with a specific annotation queueId.
|
||||
dataType:
|
||||
type: optional<commons.ScoreDataType>
|
||||
docs: Retrieve only scores with a specific dataType.
|
||||
traceTags:
|
||||
type: optional<string>
|
||||
allow-multiple: true
|
||||
docs: Only scores linked to traces that include all of these tags will be returned.
|
||||
response: GetScoresResponse
|
||||
get-by-id:
|
||||
docs: Get a score (supports both trace and session scores)
|
||||
method: GET
|
||||
path: /scores/{scoreId}
|
||||
path-parameters:
|
||||
scoreId:
|
||||
type: string
|
||||
docs: The unique langfuse identifier of a score
|
||||
response: commons.Score
|
||||
|
||||
types:
|
||||
GetScoresResponseTraceData:
|
||||
properties:
|
||||
userId:
|
||||
type: optional<string>
|
||||
docs: The user ID associated with the trace referenced by score
|
||||
tags:
|
||||
type: optional<list<string>>
|
||||
docs: A list of tags associated with the trace referenced by score
|
||||
environment:
|
||||
type: optional<string>
|
||||
docs: The environment of the trace referenced by score
|
||||
|
||||
GetScoresResponseDataNumeric:
|
||||
extends: commons.NumericScore
|
||||
properties:
|
||||
trace: optional<GetScoresResponseTraceData>
|
||||
|
||||
GetScoresResponseDataCategorical:
|
||||
extends: commons.CategoricalScore
|
||||
properties:
|
||||
trace: optional<GetScoresResponseTraceData>
|
||||
|
||||
GetScoresResponseDataBoolean:
|
||||
extends: commons.BooleanScore
|
||||
properties:
|
||||
trace: optional<GetScoresResponseTraceData>
|
||||
|
||||
GetScoresResponseData:
|
||||
discriminant: dataType
|
||||
union:
|
||||
NUMERIC: GetScoresResponseDataNumeric
|
||||
CATEGORICAL: GetScoresResponseDataCategorical
|
||||
BOOLEAN: GetScoresResponseDataBoolean
|
||||
|
||||
GetScoresResponse:
|
||||
properties:
|
||||
data: list<GetScoresResponseData>
|
||||
meta: pagination.MetaResponse
|
||||
@@ -7,77 +7,13 @@ service:
|
||||
base-path: /api/public
|
||||
endpoints:
|
||||
create:
|
||||
docs: Create a score
|
||||
docs: Create a score (supports both trace and session scores)
|
||||
method: POST
|
||||
path: /scores
|
||||
request: CreateScoreRequest
|
||||
response: CreateScoreResponse
|
||||
get:
|
||||
docs: Get a list of scores
|
||||
method: GET
|
||||
path: /scores
|
||||
request:
|
||||
name: GetScoresRequest
|
||||
query-parameters:
|
||||
page:
|
||||
type: optional<integer>
|
||||
docs: Page number, starts at 1.
|
||||
limit:
|
||||
type: optional<integer>
|
||||
docs: Limit of items per page. If you encounter api issues due to too large page sizes, try to reduce the limit.
|
||||
userId:
|
||||
type: optional<string>
|
||||
docs: Retrieve only scores with this userId associated to the trace.
|
||||
name:
|
||||
type: optional<string>
|
||||
docs: Retrieve only scores with this name.
|
||||
fromTimestamp:
|
||||
type: optional<datetime>
|
||||
docs: Optional filter to only include scores created on or after a certain datetime (ISO 8601)
|
||||
toTimestamp:
|
||||
type: optional<datetime>
|
||||
docs: Optional filter to only include scores created before a certain datetime (ISO 8601)
|
||||
environment:
|
||||
type: optional<string>
|
||||
allow-multiple: true
|
||||
docs: Optional filter for scores where the environment is one of the provided values.
|
||||
source:
|
||||
type: optional<commons.ScoreSource>
|
||||
docs: Retrieve only scores from a specific source.
|
||||
operator:
|
||||
type: optional<string>
|
||||
docs: Retrieve only scores with <operator> value.
|
||||
value:
|
||||
type: optional<double>
|
||||
docs: Retrieve only scores with <operator> value.
|
||||
scoreIds:
|
||||
type: optional<string>
|
||||
docs: Comma-separated list of score IDs to limit the results to.
|
||||
configId:
|
||||
type: optional<string>
|
||||
docs: Retrieve only scores with a specific configId.
|
||||
queueId:
|
||||
type: optional<string>
|
||||
docs: Retrieve only scores with a specific annotation queueId.
|
||||
dataType:
|
||||
type: optional<commons.ScoreDataType>
|
||||
docs: Retrieve only scores with a specific dataType.
|
||||
traceTags:
|
||||
type: optional<string>
|
||||
allow-multiple: true
|
||||
docs: Only scores linked to traces that include all of these tags will be returned.
|
||||
response: GetScoresResponse
|
||||
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
|
||||
docs: Delete a score (supports both trace and session scores)
|
||||
method: DELETE
|
||||
path: /scores/{scoreId}
|
||||
path-parameters:
|
||||
@@ -88,13 +24,16 @@ types:
|
||||
CreateScoreRequest:
|
||||
properties:
|
||||
id: optional<string>
|
||||
traceId: string
|
||||
traceId: optional<string>
|
||||
sessionId: optional<string>
|
||||
observationId: optional<string>
|
||||
datasetRunId: optional<string>
|
||||
name: string
|
||||
value:
|
||||
type: commons.CreateScoreValue
|
||||
docs: The value of the score. Must be passed as string for categorical scores, and numeric for boolean and numeric scores. Boolean score values must equal either 1 or 0 (true or false)
|
||||
observationId: optional<string>
|
||||
comment: optional<string>
|
||||
metadata: optional<unknown>
|
||||
environment:
|
||||
type: optional<string>
|
||||
docs: The environment of the score. Can be any lowercase alphanumeric string with hyphens and underscores that does not start with 'langfuse'.
|
||||
@@ -148,41 +87,3 @@ types:
|
||||
id:
|
||||
type: string
|
||||
docs: The id of the created object in Langfuse
|
||||
GetScoresResponseTraceData:
|
||||
properties:
|
||||
userId:
|
||||
type: optional<string>
|
||||
docs: The user ID associated with the trace referenced by score
|
||||
tags:
|
||||
type: optional<list<string>>
|
||||
docs: A list of tags associated with the trace referenced by score
|
||||
environment:
|
||||
type: optional<string>
|
||||
docs: The environment of the trace referenced by score
|
||||
|
||||
GetScoresResponseDataNumeric:
|
||||
extends: commons.NumericScore
|
||||
properties:
|
||||
trace: GetScoresResponseTraceData
|
||||
|
||||
GetScoresResponseDataCategorical:
|
||||
extends: commons.CategoricalScore
|
||||
properties:
|
||||
trace: GetScoresResponseTraceData
|
||||
|
||||
GetScoresResponseDataBoolean:
|
||||
extends: commons.BooleanScore
|
||||
properties:
|
||||
trace: GetScoresResponseTraceData
|
||||
|
||||
GetScoresResponseData:
|
||||
discriminant: dataType
|
||||
union:
|
||||
NUMERIC: GetScoresResponseDataNumeric
|
||||
CATEGORICAL: GetScoresResponseDataCategorical
|
||||
BOOLEAN: GetScoresResponseDataBoolean
|
||||
|
||||
GetScoresResponse:
|
||||
properties:
|
||||
data: list<GetScoresResponseData>
|
||||
meta: pagination.MetaResponse
|
||||
|
||||
+3
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "langfuse",
|
||||
"version": "3.39.0",
|
||||
"version": "3.61.0",
|
||||
"author": "engineering@langfuse.com",
|
||||
"license": "MIT",
|
||||
"private": true,
|
||||
@@ -23,6 +23,8 @@
|
||||
"build": "turbo run build",
|
||||
"start": "turbo run start",
|
||||
"dev": "turbo run dev",
|
||||
"dev:worker": "turbo run dev --filter=worker",
|
||||
"dev:web": "turbo run dev --filter=web",
|
||||
"lint": "turbo run lint",
|
||||
"test": "turbo run test",
|
||||
"release": "dotenv -e ../.env -- release-it",
|
||||
|
||||
+1
@@ -0,0 +1 @@
|
||||
ALTER TABLE scores ON CLUSTER default DROP COLUMN IF EXISTS metadata;
|
||||
+1
@@ -0,0 +1 @@
|
||||
ALTER TABLE scores ON CLUSTER default ADD COLUMN metadata Map(LowCardinality(String), String) AFTER comment;
|
||||
+1
@@ -0,0 +1 @@
|
||||
DROP TABLE blob_storage_file_log ON CLUSTER default;
|
||||
@@ -0,0 +1,21 @@
|
||||
CREATE TABLE blob_storage_file_log ON CLUSTER default (
|
||||
`id` String,
|
||||
`project_id` String,
|
||||
`entity_type` String,
|
||||
`entity_id` String,
|
||||
`event_id` String,
|
||||
|
||||
`bucket_name` String,
|
||||
`bucket_path` String,
|
||||
|
||||
`created_at` DateTime64(3) DEFAULT now(),
|
||||
`updated_at` DateTime64(3) DEFAULT now(),
|
||||
event_ts DateTime64(3),
|
||||
is_deleted UInt8,
|
||||
) ENGINE = ReplicatedReplacingMergeTree(event_ts, is_deleted)
|
||||
ORDER BY (
|
||||
project_id,
|
||||
entity_type,
|
||||
entity_id,
|
||||
event_id
|
||||
);
|
||||
+1
@@ -0,0 +1 @@
|
||||
ALTER TABLE scores ON CLUSTER default DROP COLUMN IF EXISTS session_id SETTINGS mutations_sync = 2;
|
||||
+1
@@ -0,0 +1 @@
|
||||
ALTER TABLE scores ON CLUSTER default ADD COLUMN session_id Nullable(String) AFTER trace_id SETTINGS mutations_sync = 2;
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE scores ON CLUSTER default ADD INDEX IF NOT EXISTS idx_project_trace_observation (project_id, trace_id, observation_id) TYPE bloom_filter(0.001) GRANULARITY 1 SETTINGS mutations_sync = 2;
|
||||
ALTER TABLE scores ON CLUSTER default MATERIALIZE INDEX IF EXISTS idx_project_trace_observation SETTINGS mutations_sync = 2;
|
||||
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE scores ON CLUSTER default DROP INDEX IF EXISTS idx_project_trace_observation SETTINGS mutations_sync = 2;
|
||||
|
||||
+1
@@ -0,0 +1 @@
|
||||
ALTER TABLE scores ON CLUSTER default MODIFY COLUMN trace_id Nullable(String) SETTINGS mutations_sync = 2;
|
||||
+1
@@ -0,0 +1 @@
|
||||
ALTER TABLE scores ON CLUSTER default MODIFY COLUMN trace_id Nullable(String) SETTINGS mutations_sync = 2;
|
||||
@@ -0,0 +1 @@
|
||||
ALTER TABLE scores ON CLUSTER default DROP INDEX IF EXISTS idx_project_trace_observation SETTINGS mutations_sync = 2;
|
||||
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE scores ON CLUSTER default ADD INDEX IF NOT EXISTS idx_project_trace_observation (project_id, trace_id, observation_id) TYPE bloom_filter(0.001) GRANULARITY 1 SETTINGS mutations_sync = 2;
|
||||
ALTER TABLE scores ON CLUSTER default MATERIALIZE INDEX IF EXISTS idx_project_trace_observation SETTINGS mutations_sync = 2;
|
||||
@@ -0,0 +1 @@
|
||||
ALTER TABLE scores ON CLUSTER default DROP INDEX IF EXISTS idx_project_session SETTINGS mutations_sync = 2;
|
||||
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE scores ON CLUSTER default ADD INDEX IF NOT EXISTS idx_project_session (project_id, session_id) TYPE bloom_filter(0.001) GRANULARITY 1 SETTINGS mutations_sync = 2;
|
||||
ALTER TABLE scores ON CLUSTER default MATERIALIZE INDEX IF EXISTS idx_project_session SETTINGS mutations_sync = 2;
|
||||
@@ -0,0 +1 @@
|
||||
ALTER TABLE scores ON CLUSTER default DROP COLUMN IF EXISTS dataset_run_id SETTINGS mutations_sync = 2;
|
||||
@@ -0,0 +1 @@
|
||||
ALTER TABLE scores ON CLUSTER default ADD COLUMN dataset_run_id Nullable(String) AFTER session_id SETTINGS mutations_sync = 2;
|
||||
@@ -0,0 +1 @@
|
||||
ALTER TABLE scores ON CLUSTER default DROP INDEX IF EXISTS idx_project_dataset_run SETTINGS mutations_sync = 2;
|
||||
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE scores ON CLUSTER default ADD INDEX IF NOT EXISTS idx_project_dataset_run (project_id, dataset_run_id) TYPE bloom_filter(0.001) GRANULARITY 1 SETTINGS mutations_sync = 2;
|
||||
ALTER TABLE scores ON CLUSTER default MATERIALIZE INDEX IF EXISTS idx_project_dataset_run SETTINGS mutations_sync = 2;
|
||||
+1
@@ -0,0 +1 @@
|
||||
ALTER TABLE scores DROP COLUMN IF EXISTS metadata;
|
||||
+1
@@ -0,0 +1 @@
|
||||
ALTER TABLE scores ADD COLUMN metadata Map(LowCardinality(String), String) AFTER comment;
|
||||
+1
@@ -0,0 +1 @@
|
||||
DROP TABLE blob_storage_file_log;
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
CREATE TABLE blob_storage_file_log
|
||||
(
|
||||
`id` String,
|
||||
`project_id` String,
|
||||
`entity_type` String,
|
||||
`entity_id` String,
|
||||
`event_id` String,
|
||||
|
||||
`bucket_name` String,
|
||||
`bucket_path` String,
|
||||
|
||||
`created_at` DateTime64(3) DEFAULT now(),
|
||||
`updated_at` DateTime64(3) DEFAULT now(),
|
||||
event_ts DateTime64(3),
|
||||
is_deleted UInt8,
|
||||
) ENGINE = ReplacingMergeTree(event_ts, is_deleted)
|
||||
ORDER BY (
|
||||
project_id,
|
||||
entity_type,
|
||||
entity_id,
|
||||
event_id
|
||||
);
|
||||
+1
@@ -0,0 +1 @@
|
||||
ALTER TABLE scores DROP COLUMN IF EXISTS session_id SETTINGS mutations_sync = 2;
|
||||
+1
@@ -0,0 +1 @@
|
||||
ALTER TABLE scores ADD COLUMN session_id Nullable(String) AFTER trace_id SETTINGS mutations_sync = 2;
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE scores ADD INDEX IF NOT EXISTS idx_project_trace_observation (project_id, trace_id, observation_id) TYPE bloom_filter(0.001) GRANULARITY 1 SETTINGS mutations_sync = 2;
|
||||
ALTER TABLE scores MATERIALIZE INDEX IF EXISTS idx_project_trace_observation SETTINGS mutations_sync = 2;
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE scores DROP INDEX IF EXISTS idx_project_trace_observation SETTINGS mutations_sync = 2;
|
||||
|
||||
+1
@@ -0,0 +1 @@
|
||||
ALTER TABLE scores MODIFY COLUMN trace_id Nullable(String) SETTINGS mutations_sync = 2;
|
||||
+1
@@ -0,0 +1 @@
|
||||
ALTER TABLE scores MODIFY COLUMN trace_id Nullable(String) SETTINGS mutations_sync = 2;
|
||||
@@ -0,0 +1 @@
|
||||
ALTER TABLE scores DROP INDEX IF EXISTS idx_project_trace_observation SETTINGS mutations_sync = 2;
|
||||
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE scores ADD INDEX IF NOT EXISTS idx_project_trace_observation (project_id, trace_id, observation_id) TYPE bloom_filter(0.001) GRANULARITY 1 SETTINGS mutations_sync = 2;
|
||||
ALTER TABLE scores MATERIALIZE INDEX IF EXISTS idx_project_trace_observation SETTINGS mutations_sync = 2;
|
||||
+1
@@ -0,0 +1 @@
|
||||
ALTER TABLE scores DROP INDEX IF EXISTS idx_project_session SETTINGS mutations_sync = 2;
|
||||
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE scores ADD INDEX IF NOT EXISTS idx_project_session (project_id, session_id) TYPE bloom_filter(0.001) GRANULARITY 1 SETTINGS mutations_sync = 2;
|
||||
ALTER TABLE scores MATERIALIZE INDEX IF EXISTS idx_project_session SETTINGS mutations_sync = 2;
|
||||
+1
@@ -0,0 +1 @@
|
||||
ALTER TABLE scores DROP COLUMN IF EXISTS dataset_run_id SETTINGS mutations_sync = 2;
|
||||
@@ -0,0 +1 @@
|
||||
ALTER TABLE scores ADD COLUMN dataset_run_id Nullable(String) AFTER session_id SETTINGS mutations_sync = 2;
|
||||
@@ -0,0 +1 @@
|
||||
ALTER TABLE scores DROP INDEX IF EXISTS idx_project_dataset_run SETTINGS mutations_sync = 2;
|
||||
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE scores ADD INDEX IF NOT EXISTS idx_project_dataset_run (project_id, dataset_run_id) TYPE bloom_filter(0.001) GRANULARITY 1 SETTINGS mutations_sync = 2;
|
||||
ALTER TABLE scores MATERIALIZE INDEX IF EXISTS idx_project_dataset_run SETTINGS mutations_sync = 2;
|
||||
@@ -33,7 +33,7 @@
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"dev": "tsc --watch",
|
||||
"lint": "eslint . --ext .js,.jsx,.ts,.tsx --max-warnings 64",
|
||||
"lint": "eslint . --ext .js,.jsx,.ts,.tsx --max-warnings 65",
|
||||
"lint:fix": "eslint . --ext .js,.jsx,.ts,.tsx --fix",
|
||||
"db:migrate": "DISABLE_ERD=false dotenv -e ../../.env -- npx prisma migrate dev",
|
||||
"db:push": "DISABLE_ERD=false dotenv -e ../../.env -- npx prisma db push",
|
||||
@@ -61,6 +61,7 @@
|
||||
"@aws-sdk/s3-request-presigner": "^3.679.0",
|
||||
"@azure/storage-blob": "^12.26.0",
|
||||
"@clickhouse/client": "^1.4.0",
|
||||
"@google-cloud/storage": "^7.15.2",
|
||||
"@langchain/anthropic": "^0.3.12",
|
||||
"@langchain/aws": "^0.1.3",
|
||||
"@langchain/core": "^0.3.37",
|
||||
@@ -84,12 +85,13 @@
|
||||
"langchain": "^0.3.15",
|
||||
"langfuse-langchain": "3.30.3",
|
||||
"lodash": "^4.17.21",
|
||||
"lossless-json": "^4.0.2",
|
||||
"next-auth": "^4.24.11",
|
||||
"nodemailer": "^6.9.15",
|
||||
"prisma-extension-kysely": "^2.1.0",
|
||||
"uuid": "^9.0.1",
|
||||
"winston": "^3.15.0",
|
||||
"zod": "^3.23.8",
|
||||
"zod": "^3.24.4",
|
||||
"zod-to-json-schema": "^3.23.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -4,6 +4,11 @@ export type Generated<T> = T extends ColumnType<infer S, infer I, infer U>
|
||||
: ColumnType<T, T | undefined, T>;
|
||||
export type Timestamp = ColumnType<Date, Date | string, Date | string>;
|
||||
|
||||
export const ApiKeyScope = {
|
||||
ORGANIZATION: "ORGANIZATION",
|
||||
PROJECT: "PROJECT"
|
||||
} as const;
|
||||
export type ApiKeyScope = (typeof ApiKeyScope)[keyof typeof ApiKeyScope];
|
||||
export const Role = {
|
||||
OWNER: "OWNER",
|
||||
ADMIN: "ADMIN",
|
||||
@@ -80,6 +85,34 @@ export const JobExecutionStatus = {
|
||||
CANCELLED: "CANCELLED"
|
||||
} as const;
|
||||
export type JobExecutionStatus = (typeof JobExecutionStatus)[keyof typeof JobExecutionStatus];
|
||||
export const BlobStorageIntegrationFileType = {
|
||||
JSON: "JSON",
|
||||
CSV: "CSV",
|
||||
JSONL: "JSONL"
|
||||
} as const;
|
||||
export type BlobStorageIntegrationFileType = (typeof BlobStorageIntegrationFileType)[keyof typeof BlobStorageIntegrationFileType];
|
||||
export const BlobStorageIntegrationType = {
|
||||
S3: "S3",
|
||||
S3_COMPATIBLE: "S3_COMPATIBLE",
|
||||
AZURE_BLOB_STORAGE: "AZURE_BLOB_STORAGE"
|
||||
} as const;
|
||||
export type BlobStorageIntegrationType = (typeof BlobStorageIntegrationType)[keyof typeof BlobStorageIntegrationType];
|
||||
export const DashboardWidgetViews = {
|
||||
TRACES: "TRACES",
|
||||
OBSERVATIONS: "OBSERVATIONS",
|
||||
SCORES_NUMERIC: "SCORES_NUMERIC",
|
||||
SCORES_CATEGORICAL: "SCORES_CATEGORICAL"
|
||||
} as const;
|
||||
export type DashboardWidgetViews = (typeof DashboardWidgetViews)[keyof typeof DashboardWidgetViews];
|
||||
export const DashboardWidgetChartType = {
|
||||
LINE_TIME_SERIES: "LINE_TIME_SERIES",
|
||||
BAR_TIME_SERIES: "BAR_TIME_SERIES",
|
||||
HORIZONTAL_BAR: "HORIZONTAL_BAR",
|
||||
VERTICAL_BAR: "VERTICAL_BAR",
|
||||
PIE: "PIE",
|
||||
NUMBER: "NUMBER"
|
||||
} as const;
|
||||
export type DashboardWidgetChartType = (typeof DashboardWidgetChartType)[keyof typeof DashboardWidgetChartType];
|
||||
export type Account = {
|
||||
id: string;
|
||||
user_id: string;
|
||||
@@ -131,7 +164,9 @@ export type ApiKey = {
|
||||
display_secret_key: string;
|
||||
last_used_at: Timestamp | null;
|
||||
expires_at: Timestamp | null;
|
||||
project_id: string;
|
||||
project_id: string | null;
|
||||
organization_id: string | null;
|
||||
scope: Generated<ApiKeyScope>;
|
||||
};
|
||||
export type AuditLog = {
|
||||
id: string;
|
||||
@@ -188,6 +223,24 @@ export type BillingMeterBackup = {
|
||||
created_at: Generated<Timestamp>;
|
||||
updated_at: Generated<Timestamp>;
|
||||
};
|
||||
export type BlobStorageIntegration = {
|
||||
project_id: string;
|
||||
type: BlobStorageIntegrationType;
|
||||
bucket_name: string;
|
||||
prefix: string;
|
||||
access_key_id: string;
|
||||
secret_access_key: string;
|
||||
region: string;
|
||||
endpoint: string | null;
|
||||
force_path_style: boolean;
|
||||
next_sync_at: Timestamp | null;
|
||||
last_sync_at: Timestamp | null;
|
||||
enabled: boolean;
|
||||
export_frequency: string;
|
||||
file_type: Generated<BlobStorageIntegrationFileType>;
|
||||
created_at: Generated<Timestamp>;
|
||||
updated_at: Generated<Timestamp>;
|
||||
};
|
||||
export type Comment = {
|
||||
id: string;
|
||||
project_id: string;
|
||||
@@ -204,6 +257,33 @@ export type CronJobs = {
|
||||
job_started_at: Timestamp | null;
|
||||
state: string | null;
|
||||
};
|
||||
export type Dashboard = {
|
||||
id: string;
|
||||
created_at: Generated<Timestamp>;
|
||||
updated_at: Generated<Timestamp>;
|
||||
created_by: string | null;
|
||||
updated_by: string | null;
|
||||
project_id: string | null;
|
||||
name: string;
|
||||
description: string;
|
||||
definition: unknown;
|
||||
};
|
||||
export type DashboardWidget = {
|
||||
id: string;
|
||||
created_at: Generated<Timestamp>;
|
||||
updated_at: Generated<Timestamp>;
|
||||
created_by: string | null;
|
||||
updated_by: string | null;
|
||||
project_id: string | null;
|
||||
name: string;
|
||||
description: string;
|
||||
view: DashboardWidgetViews;
|
||||
dimensions: unknown;
|
||||
metrics: unknown;
|
||||
filters: unknown;
|
||||
chart_type: DashboardWidgetChartType;
|
||||
chart_config: unknown;
|
||||
};
|
||||
export type Dataset = {
|
||||
id: string;
|
||||
project_id: string;
|
||||
@@ -378,6 +458,24 @@ export type LlmApiKeys = {
|
||||
config: unknown | null;
|
||||
project_id: string;
|
||||
};
|
||||
export type LlmSchema = {
|
||||
id: string;
|
||||
created_at: Generated<Timestamp>;
|
||||
updated_at: Generated<Timestamp>;
|
||||
project_id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
schema: unknown;
|
||||
};
|
||||
export type LlmTool = {
|
||||
id: string;
|
||||
created_at: Generated<Timestamp>;
|
||||
updated_at: Generated<Timestamp>;
|
||||
project_id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
parameters: unknown;
|
||||
};
|
||||
export type Media = {
|
||||
id: string;
|
||||
sha_256_hash: string;
|
||||
@@ -434,6 +532,7 @@ export type Organization = {
|
||||
created_at: Generated<Timestamp>;
|
||||
updated_at: Generated<Timestamp>;
|
||||
cloud_config: unknown | null;
|
||||
metadata: unknown | null;
|
||||
};
|
||||
export type OrganizationMembership = {
|
||||
id: string;
|
||||
@@ -467,6 +566,7 @@ export type Project = {
|
||||
deleted_at: Timestamp | null;
|
||||
name: string;
|
||||
retention_days: number | null;
|
||||
metadata: unknown | null;
|
||||
};
|
||||
export type ProjectMembership = {
|
||||
org_membership_id: string;
|
||||
@@ -492,12 +592,22 @@ export type Prompt = {
|
||||
labels: Generated<string[]>;
|
||||
commit_message: string | null;
|
||||
};
|
||||
export type QueueBackUp = {
|
||||
export type PromptDependency = {
|
||||
id: string;
|
||||
project_id: string | null;
|
||||
queue_name: string;
|
||||
content: unknown;
|
||||
created_at: Generated<Timestamp>;
|
||||
updated_at: Generated<Timestamp>;
|
||||
project_id: string;
|
||||
parent_id: string;
|
||||
child_name: string;
|
||||
child_label: string | null;
|
||||
child_version: number | null;
|
||||
};
|
||||
export type PromptProtectedLabels = {
|
||||
id: string;
|
||||
created_at: Generated<Timestamp>;
|
||||
updated_at: Generated<Timestamp>;
|
||||
project_id: string;
|
||||
label: string;
|
||||
};
|
||||
export type ScoreConfig = {
|
||||
id: string;
|
||||
@@ -525,6 +635,21 @@ export type SsoConfig = {
|
||||
auth_provider: string;
|
||||
auth_config: unknown | null;
|
||||
};
|
||||
export type TableViewPreset = {
|
||||
id: string;
|
||||
created_at: Generated<Timestamp>;
|
||||
updated_at: Generated<Timestamp>;
|
||||
project_id: string;
|
||||
name: string;
|
||||
table_name: string;
|
||||
created_by: string | null;
|
||||
updated_by: string | null;
|
||||
filters: unknown;
|
||||
column_order: unknown;
|
||||
column_visibility: unknown;
|
||||
search_query: string | null;
|
||||
order_by: unknown | null;
|
||||
};
|
||||
export type TraceMedia = {
|
||||
id: string;
|
||||
project_id: string;
|
||||
@@ -569,8 +694,11 @@ export type DB = {
|
||||
background_migrations: BackgroundMigration;
|
||||
batch_exports: BatchExport;
|
||||
billing_meter_backups: BillingMeterBackup;
|
||||
blob_storage_integrations: BlobStorageIntegration;
|
||||
comments: Comment;
|
||||
cron_jobs: CronJobs;
|
||||
dashboard_widgets: DashboardWidget;
|
||||
dashboards: Dashboard;
|
||||
dataset_items: DatasetItem;
|
||||
dataset_run_items: DatasetRunItems;
|
||||
dataset_runs: DatasetRuns;
|
||||
@@ -579,6 +707,8 @@ export type DB = {
|
||||
job_configurations: JobConfiguration;
|
||||
job_executions: JobExecution;
|
||||
llm_api_keys: LlmApiKeys;
|
||||
llm_schemas: LlmSchema;
|
||||
llm_tools: LlmTool;
|
||||
media: Media;
|
||||
membership_invitations: MembershipInvitation;
|
||||
models: Model;
|
||||
@@ -590,12 +720,14 @@ export type DB = {
|
||||
prices: Price;
|
||||
project_memberships: ProjectMembership;
|
||||
projects: Project;
|
||||
prompt_dependencies: PromptDependency;
|
||||
prompt_protected_labels: PromptProtectedLabels;
|
||||
prompts: Prompt;
|
||||
queue_backups: QueueBackUp;
|
||||
score_configs: ScoreConfig;
|
||||
scores: LegacyPrismaScore;
|
||||
Session: Session;
|
||||
sso_configs: SsoConfig;
|
||||
table_view_presets: TableViewPreset;
|
||||
trace_media: TraceMedia;
|
||||
trace_sessions: TraceSession;
|
||||
traces: LegacyPrismaTrace;
|
||||
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
CREATE TABLE "prompt_dependencies" (
|
||||
"id" TEXT NOT NULL,
|
||||
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updated_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"project_id" TEXT NOT NULL,
|
||||
"parent_id" TEXT NOT NULL,
|
||||
"child_name" TEXT NOT NULL,
|
||||
"child_label" TEXT,
|
||||
"child_version" INTEGER,
|
||||
|
||||
CONSTRAINT "prompt_dependencies_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
ALTER TABLE "prompt_dependencies" ADD CONSTRAINT "prompt_dependencies_project_id_fkey" FOREIGN KEY ("project_id") REFERENCES "projects"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
ALTER TABLE "prompt_dependencies" ADD CONSTRAINT "prompt_dependencies_parent_id_fkey" FOREIGN KEY ("parent_id") REFERENCES "prompts"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
CREATE INDEX "prompt_dependencies_project_id_parent_id" ON "prompt_dependencies"("project_id", "parent_id");
|
||||
CREATE INDEX "prompt_dependencies_project_id_child_name" ON "prompt_dependencies"("project_id", "child_name");
|
||||
@@ -0,0 +1,2 @@
|
||||
-- DropTable
|
||||
DROP TABLE "queue_backups";
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
-- CreateEnum
|
||||
CREATE TYPE "BlobStorageIntegrationType" AS ENUM ('S3', 'S3_COMPATIBLE', 'AZURE_BLOB_STORAGE');
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "blob_storage_integrations" (
|
||||
"project_id" TEXT NOT NULL,
|
||||
"type" "BlobStorageIntegrationType" NOT NULL,
|
||||
"bucket_name" TEXT NOT NULL,
|
||||
"prefix" TEXT NOT NULL,
|
||||
"access_key_id" TEXT NOT NULL,
|
||||
"secret_access_key" TEXT NOT NULL,
|
||||
"region" TEXT NOT NULL,
|
||||
"endpoint" TEXT,
|
||||
"force_path_style" BOOLEAN NOT NULL,
|
||||
"next_sync_at" TIMESTAMP(3),
|
||||
"last_sync_at" TIMESTAMP(3),
|
||||
"enabled" BOOLEAN NOT NULL,
|
||||
"export_frequency" TEXT NOT NULL,
|
||||
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updated_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "blob_storage_integrations_pkey" PRIMARY KEY ("project_id")
|
||||
);
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "blob_storage_integrations" ADD CONSTRAINT "blob_storage_integrations_project_id_fkey" FOREIGN KEY ("project_id") REFERENCES "projects"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
-- CreateTable
|
||||
CREATE TABLE "llm_schemas" (
|
||||
"id" TEXT NOT NULL,
|
||||
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updated_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"project_id" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"description" TEXT NOT NULL,
|
||||
"schema" JSON NOT NULL,
|
||||
|
||||
CONSTRAINT "llm_schemas_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "llm_tools" (
|
||||
"id" TEXT NOT NULL,
|
||||
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updated_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"project_id" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"description" TEXT NOT NULL,
|
||||
"parameters" JSON NOT NULL,
|
||||
|
||||
CONSTRAINT "llm_tools_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "llm_schemas_project_id_name_key" ON "llm_schemas"("project_id", "name");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "llm_tools_project_id_name_key" ON "llm_tools"("project_id", "name");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "llm_schemas" ADD CONSTRAINT "llm_schemas_project_id_fkey" FOREIGN KEY ("project_id") REFERENCES "projects"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "llm_tools" ADD CONSTRAINT "llm_tools_project_id_fkey" FOREIGN KEY ("project_id") REFERENCES "projects"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
-- CreateTable
|
||||
CREATE TABLE "prompt_protected_labels" (
|
||||
"id" TEXT NOT NULL,
|
||||
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updated_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"project_id" TEXT NOT NULL,
|
||||
"label" TEXT NOT NULL,
|
||||
|
||||
CONSTRAINT "prompt_protected_labels_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "prompt_protected_labels_project_id_label_key" ON "prompt_protected_labels"("project_id", "label");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "prompt_protected_labels" ADD CONSTRAINT "prompt_protected_labels_project_id_fkey" FOREIGN KEY ("project_id") REFERENCES "projects"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
-- CreateEnum
|
||||
CREATE TYPE "BlobStorageIntegrationFileType" AS ENUM ('JSON', 'CSV', 'JSONL');
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "blob_storage_integrations" ADD COLUMN "file_type" "BlobStorageIntegrationFileType" NOT NULL DEFAULT 'CSV';
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
-- Delete duplicate membership invitations, keeping only the newest one for each email and org_id combination
|
||||
WITH ranked_invitations AS (
|
||||
SELECT
|
||||
id,
|
||||
email,
|
||||
org_id,
|
||||
ROW_NUMBER() OVER (PARTITION BY email, org_id ORDER BY updated_at DESC) as rn
|
||||
FROM membership_invitations
|
||||
)
|
||||
DELETE FROM membership_invitations
|
||||
WHERE id IN (
|
||||
SELECT id FROM ranked_invitations WHERE rn > 1
|
||||
);
|
||||
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "membership_invitations_email_org_id_key" ON "membership_invitations"("email", "org_id");
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
-- CreateEnum
|
||||
CREATE TYPE "DashboardWidgetViews" AS ENUM ('TRACES', 'OBSERVATIONS', 'SCORES_NUMERIC', 'SCORES_CATEGORICAL');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "DashboardWidgetChartType" AS ENUM ('LINE_TIME_SERIES', 'BAR_TIME_SERIES', 'HORIZONTAL_BAR', 'VERTICAL_BAR', 'PIE');
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "dashboards" (
|
||||
"id" TEXT NOT NULL,
|
||||
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updated_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"created_by" TEXT,
|
||||
"updated_by" TEXT,
|
||||
"project_id" TEXT,
|
||||
"name" TEXT NOT NULL,
|
||||
"description" TEXT NOT NULL,
|
||||
"definition" JSONB NOT NULL,
|
||||
|
||||
CONSTRAINT "dashboards_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "dashboard_widgets" (
|
||||
"id" TEXT NOT NULL,
|
||||
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updated_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"created_by" TEXT,
|
||||
"updated_by" TEXT,
|
||||
"project_id" TEXT,
|
||||
"name" TEXT NOT NULL,
|
||||
"description" TEXT NOT NULL,
|
||||
"view" "DashboardWidgetViews" NOT NULL,
|
||||
"dimensions" JSONB NOT NULL,
|
||||
"metrics" JSONB NOT NULL,
|
||||
"filters" JSONB NOT NULL,
|
||||
"chart_type" "DashboardWidgetChartType" NOT NULL,
|
||||
"chart_config" JSONB NOT NULL,
|
||||
|
||||
CONSTRAINT "dashboard_widgets_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "dashboards" ADD CONSTRAINT "dashboards_created_by_fkey" FOREIGN KEY ("created_by") REFERENCES "users"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "dashboards" ADD CONSTRAINT "dashboards_updated_by_fkey" FOREIGN KEY ("updated_by") REFERENCES "users"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "dashboards" ADD CONSTRAINT "dashboards_project_id_fkey" FOREIGN KEY ("project_id") REFERENCES "projects"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "dashboard_widgets" ADD CONSTRAINT "dashboard_widgets_created_by_fkey" FOREIGN KEY ("created_by") REFERENCES "users"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "dashboard_widgets" ADD CONSTRAINT "dashboard_widgets_updated_by_fkey" FOREIGN KEY ("updated_by") REFERENCES "users"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "dashboard_widgets" ADD CONSTRAINT "dashboard_widgets_project_id_fkey" FOREIGN KEY ("project_id") REFERENCES "projects"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
-- CreateEnum
|
||||
CREATE TYPE "ApiKeyScope" AS ENUM ('ORGANIZATION', 'PROJECT');
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "api_keys" ADD COLUMN "organization_id" TEXT,
|
||||
ADD COLUMN "scope" "ApiKeyScope" NOT NULL DEFAULT 'PROJECT',
|
||||
ALTER COLUMN "project_id" DROP NOT NULL;
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "api_keys_organization_id_idx" ON "api_keys"("organization_id");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "api_keys" ADD CONSTRAINT "api_keys_organization_id_fkey" FOREIGN KEY ("organization_id") REFERENCES "organizations"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
-- AlterTable
|
||||
ALTER TABLE "organizations" ADD COLUMN "metadata" JSONB;
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "projects" ADD COLUMN "metadata" JSONB;
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
INSERT INTO background_migrations (id, name, script, args)
|
||||
VALUES ('c19b91d9-f9a2-468b-8209-95578f970c5b', '20250417_1737_migrate_event_log_to_blob_storage', 'migrateEventLogToBlobStorageRefTable', '{}');
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
-- CreateTable
|
||||
CREATE TABLE "table_view_presets" (
|
||||
"id" TEXT NOT NULL,
|
||||
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updated_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"project_id" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"table_name" TEXT NOT NULL,
|
||||
"created_by" TEXT,
|
||||
"updated_by" TEXT,
|
||||
"filters" JSONB NOT NULL,
|
||||
"column_order" JSONB NOT NULL,
|
||||
"column_visibility" JSONB NOT NULL,
|
||||
"search_query" TEXT,
|
||||
"order_by" JSONB,
|
||||
|
||||
CONSTRAINT "table_view_presets_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "table_view_presets_project_id_table_name_name_key" ON "table_view_presets"("project_id", "table_name", "name");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "table_view_presets" ADD CONSTRAINT "table_view_presets_created_by_fkey" FOREIGN KEY ("created_by") REFERENCES "users"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "table_view_presets" ADD CONSTRAINT "table_view_presets_updated_by_fkey" FOREIGN KEY ("updated_by") REFERENCES "users"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "table_view_presets" ADD CONSTRAINT "table_view_presets_project_id_fkey" FOREIGN KEY ("project_id") REFERENCES "projects"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
-- CreateIndex
|
||||
CREATE INDEX CONCURRENTLY IF NOT EXISTS "trace_media_project_id_media_id_idx" ON "trace_media"("project_id", "media_id");
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
-- CreateIndex
|
||||
CREATE INDEX CONCURRENTLY IF NOT EXISTS "observation_media_project_id_media_id_idx" ON "observation_media"("project_id", "media_id");
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
-- Index cannot be created concurrently in a transaction, so we need to create it separately
|
||||
-- Prerequisite for migration 20250518075613_media_relax_id_uniqueness_to_project_only
|
||||
CREATE UNIQUE INDEX CONCURRENTLY IF NOT EXISTS "media_project_id_id_key" ON "media"("project_id", "id");
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
Warnings:
|
||||
|
||||
- The primary key for the `media` table will be changed. If it partially fails, the table could be left without primary key constraint.
|
||||
- A unique constraint covering the columns `[project_id,id]` on the table `media` will be added. If there are existing duplicate values, this will fail.
|
||||
|
||||
*/
|
||||
-- DropForeignKey
|
||||
ALTER TABLE "observation_media" DROP CONSTRAINT "observation_media_media_id_fkey";
|
||||
|
||||
-- DropForeignKey
|
||||
ALTER TABLE "trace_media" DROP CONSTRAINT "trace_media_media_id_fkey";
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "media" DROP CONSTRAINT "media_pkey";
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "trace_media" ADD CONSTRAINT "trace_media_media_id_project_id_fkey" FOREIGN KEY ("media_id", "project_id") REFERENCES "media"("id", "project_id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "observation_media" ADD CONSTRAINT "observation_media_media_id_project_id_fkey" FOREIGN KEY ("media_id", "project_id") REFERENCES "media"("id", "project_id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
/* Triple y and y_size in dashboards.definition->'widgets' */
|
||||
WITH updated AS (
|
||||
SELECT
|
||||
id,
|
||||
CASE
|
||||
WHEN jsonb_array_length(definition->'widgets') = 0 THEN definition
|
||||
ELSE jsonb_set(
|
||||
definition, -- original JSON
|
||||
'{widgets}', -- path to replace
|
||||
(
|
||||
SELECT jsonb_agg( -- rebuild widgets array
|
||||
/* 1) y * 3 2) y_size * 3 */
|
||||
jsonb_set(
|
||||
jsonb_set(widget, '{y}',
|
||||
to_jsonb( ((widget->>'y')::int * 3) ), /* y */
|
||||
true
|
||||
),
|
||||
'{y_size}',
|
||||
to_jsonb( ((widget->>'y_size')::int * 3) ),/* y_size */
|
||||
true
|
||||
)
|
||||
)
|
||||
FROM jsonb_array_elements(definition->'widgets') AS widget
|
||||
),
|
||||
true -- create path if absent
|
||||
)
|
||||
END AS new_def
|
||||
FROM dashboards
|
||||
)
|
||||
UPDATE dashboards d
|
||||
SET definition = u.new_def
|
||||
FROM updated u
|
||||
WHERE d.id = u.id;
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
-- AlterEnum
|
||||
ALTER TYPE "DashboardWidgetChartType" ADD VALUE 'NUMBER';
|
||||
@@ -82,6 +82,12 @@ model User {
|
||||
featureFlags String[] @default([]) @map("feature_flags")
|
||||
annotatedLockedItem AnnotationQueueItem[] @relation("LockedByUser")
|
||||
annotatedCompletedItem AnnotationQueueItem[] @relation("AnnotatorUser")
|
||||
dashboardWidgetsCreated DashboardWidget[] @relation("CreatedByUser")
|
||||
dashboardWidgetsUpdated DashboardWidget[] @relation("UpdatedByUser")
|
||||
dashboardCreated Dashboard[] @relation("CreatedByUser")
|
||||
dashboardUpdated Dashboard[] @relation("UpdatedByUser")
|
||||
tableViewPresetCreated TableViewPreset[] @relation("CreatedByUser")
|
||||
tableViewPresetUpdated TableViewPreset[] @relation("UpdatedByUser")
|
||||
|
||||
@@map("users")
|
||||
}
|
||||
@@ -101,63 +107,83 @@ model Organization {
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime @default(now()) @updatedAt @map("updated_at")
|
||||
cloudConfig Json? @map("cloud_config") // Langfuse Cloud, for zod schema see @/src/features/organizations/utils/cloudConfigSchema
|
||||
metadata Json?
|
||||
organizationMemberships OrganizationMembership[]
|
||||
projects Project[]
|
||||
MembershipInvitation MembershipInvitation[]
|
||||
ApiKey ApiKey[]
|
||||
|
||||
@@map("organizations")
|
||||
}
|
||||
|
||||
model Project {
|
||||
id String @id @default(cuid())
|
||||
orgId String @map("org_id")
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime @default(now()) @updatedAt @map("updated_at")
|
||||
deletedAt DateTime? @map("deleted_at")
|
||||
name String
|
||||
retentionDays Int? @map("retention_days")
|
||||
projectMembers ProjectMembership[]
|
||||
organization Organization @relation(fields: [orgId], references: [id], onUpdate: Cascade, onDelete: Cascade)
|
||||
apiKeys ApiKey[]
|
||||
dataset Dataset[]
|
||||
invitations MembershipInvitation[]
|
||||
sessions TraceSession[]
|
||||
Prompt Prompt[]
|
||||
Model Model[]
|
||||
EvalTemplate EvalTemplate[]
|
||||
JobConfiguration JobConfiguration[]
|
||||
JobExecution JobExecution[]
|
||||
LlmApiKeys LlmApiKeys[]
|
||||
PosthogIntegration PosthogIntegration[]
|
||||
scoreConfig ScoreConfig[]
|
||||
BatchExport BatchExport[]
|
||||
comment Comment[]
|
||||
annotationQueue AnnotationQueue[]
|
||||
annotationQueueItem AnnotationQueueItem[]
|
||||
TraceMedia TraceMedia[]
|
||||
Media Media[]
|
||||
ObservationMedia ObservationMedia[]
|
||||
LegacyTrace LegacyPrismaTrace[]
|
||||
LegacyObservation LegacyPrismaObservation[]
|
||||
LegacyScore LegacyPrismaScore[]
|
||||
id String @id @default(cuid())
|
||||
orgId String @map("org_id")
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime @default(now()) @updatedAt @map("updated_at")
|
||||
deletedAt DateTime? @map("deleted_at")
|
||||
name String
|
||||
retentionDays Int? @map("retention_days")
|
||||
metadata Json?
|
||||
projectMembers ProjectMembership[]
|
||||
organization Organization @relation(fields: [orgId], references: [id], onUpdate: Cascade, onDelete: Cascade)
|
||||
apiKeys ApiKey[]
|
||||
dataset Dataset[]
|
||||
invitations MembershipInvitation[]
|
||||
sessions TraceSession[]
|
||||
Prompt Prompt[]
|
||||
Model Model[]
|
||||
EvalTemplate EvalTemplate[]
|
||||
JobConfiguration JobConfiguration[]
|
||||
JobExecution JobExecution[]
|
||||
LlmApiKeys LlmApiKeys[]
|
||||
PosthogIntegration PosthogIntegration[]
|
||||
BlobStorageIntegration BlobStorageIntegration[]
|
||||
scoreConfig ScoreConfig[]
|
||||
BatchExport BatchExport[]
|
||||
comment Comment[]
|
||||
annotationQueue AnnotationQueue[]
|
||||
annotationQueueItem AnnotationQueueItem[]
|
||||
TraceMedia TraceMedia[]
|
||||
Media Media[]
|
||||
ObservationMedia ObservationMedia[]
|
||||
LegacyTrace LegacyPrismaTrace[]
|
||||
LegacyObservation LegacyPrismaObservation[]
|
||||
LegacyScore LegacyPrismaScore[]
|
||||
PromptDependency PromptDependency[]
|
||||
LlmSchema LlmSchema[]
|
||||
LlmTool LlmTool[]
|
||||
PromptProtectedLabels PromptProtectedLabels[]
|
||||
Dashboard Dashboard[]
|
||||
DashboardWidget DashboardWidget[]
|
||||
TableViewPreset TableViewPreset[]
|
||||
|
||||
@@index([orgId])
|
||||
@@map("projects")
|
||||
}
|
||||
|
||||
model ApiKey {
|
||||
id String @id @unique @default(cuid())
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
note String?
|
||||
publicKey String @unique @map("public_key")
|
||||
hashedSecretKey String @unique @map("hashed_secret_key")
|
||||
fastHashedSecretKey String? @unique @map("fast_hashed_secret_key")
|
||||
displaySecretKey String @map("display_secret_key")
|
||||
lastUsedAt DateTime? @map("last_used_at")
|
||||
expiresAt DateTime? @map("expires_at")
|
||||
projectId String @map("project_id")
|
||||
project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
|
||||
enum ApiKeyScope {
|
||||
ORGANIZATION
|
||||
PROJECT
|
||||
}
|
||||
|
||||
model ApiKey {
|
||||
id String @id @unique @default(cuid())
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
note String?
|
||||
publicKey String @unique @map("public_key")
|
||||
hashedSecretKey String @unique @map("hashed_secret_key")
|
||||
fastHashedSecretKey String? @unique @map("fast_hashed_secret_key")
|
||||
displaySecretKey String @map("display_secret_key")
|
||||
lastUsedAt DateTime? @map("last_used_at")
|
||||
expiresAt DateTime? @map("expires_at")
|
||||
projectId String? @map("project_id")
|
||||
project Project? @relation(fields: [projectId], references: [id], onDelete: Cascade)
|
||||
orgId String? @map("organization_id")
|
||||
organization Organization? @relation(fields: [orgId], references: [id], onDelete: Cascade)
|
||||
scope ApiKeyScope @default(PROJECT) @map("scope")
|
||||
|
||||
@@index(orgId)
|
||||
@@index(projectId)
|
||||
@@index(publicKey)
|
||||
@@index(hashedSecretKey)
|
||||
@@ -252,6 +278,7 @@ model MembershipInvitation {
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime @default(now()) @updatedAt @map("updated_at")
|
||||
|
||||
@@unique([email, orgId]) // do not include projectId as this leads to issues when processing the invites, needs new logic
|
||||
@@index([projectId])
|
||||
@@index([orgId])
|
||||
@@index([email])
|
||||
@@ -640,15 +667,16 @@ model Prompt {
|
||||
|
||||
createdBy String @map("created_by")
|
||||
|
||||
prompt Json
|
||||
name String
|
||||
version Int
|
||||
type String @default("text")
|
||||
isActive Boolean? @map("is_active") // Deprecated. To be removed once 'production' labels work as expected.
|
||||
config Json @default("{}") @db.Json
|
||||
tags String[] @default([])
|
||||
labels String[] @default([])
|
||||
commitMessage String? @map("commit_message")
|
||||
prompt Json
|
||||
name String
|
||||
version Int
|
||||
type String @default("text")
|
||||
isActive Boolean? @map("is_active") // Deprecated. To be removed once 'production' labels work as expected.
|
||||
config Json @default("{}") @db.Json
|
||||
tags String[] @default([])
|
||||
labels String[] @default([])
|
||||
commitMessage String? @map("commit_message")
|
||||
PromptDependency PromptDependency[]
|
||||
|
||||
@@unique([projectId, name, version])
|
||||
@@index([projectId, id])
|
||||
@@ -658,6 +686,38 @@ model Prompt {
|
||||
@@map("prompts")
|
||||
}
|
||||
|
||||
model PromptDependency {
|
||||
id String @id @default(cuid())
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime @default(now()) @updatedAt @map("updated_at")
|
||||
|
||||
projectId String @map("project_id")
|
||||
project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
|
||||
|
||||
parentId String @map("parent_id")
|
||||
parent Prompt @relation(fields: [parentId], references: [id], onDelete: Cascade)
|
||||
|
||||
childName String @map("child_name")
|
||||
childLabel String? @map("child_label")
|
||||
childVersion Int? @map("child_version")
|
||||
|
||||
@@index([projectId, parentId], map: "prompt_dependencies_project_id_parent_id")
|
||||
@@index([projectId, childName], map: "prompt_dependencies_project_id_child_name")
|
||||
@@map("prompt_dependencies")
|
||||
}
|
||||
|
||||
model PromptProtectedLabels {
|
||||
id String @id @default(cuid())
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime @default(now()) @updatedAt @map("updated_at")
|
||||
projectId String @map("project_id")
|
||||
project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
|
||||
label String
|
||||
|
||||
@@unique([projectId, label])
|
||||
@@map("prompt_protected_labels")
|
||||
}
|
||||
|
||||
// Update ObservationView below when making changes to this model!
|
||||
model Model {
|
||||
id String @id @default(cuid())
|
||||
@@ -836,9 +896,9 @@ model SsoConfig {
|
||||
authProvider String @map("auth_provider") // e.g. "okta", ee/sso/types.ts
|
||||
|
||||
authConfig Json? @map("auth_config")
|
||||
|
||||
// e.g. { "clientId": "1234", "clientSecret": "5678" }, null if credentials from env should be used
|
||||
// secrets like clientSecret are encrypted on the application level
|
||||
|
||||
@@map("sso_configs")
|
||||
}
|
||||
|
||||
@@ -854,6 +914,49 @@ model PosthogIntegration {
|
||||
@@map("posthog_integrations")
|
||||
}
|
||||
|
||||
model BlobStorageIntegration {
|
||||
projectId String @id @map("project_id")
|
||||
project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
|
||||
|
||||
// Blob Storage Config
|
||||
type BlobStorageIntegrationType @map("type")
|
||||
bucketName String @map("bucket_name")
|
||||
prefix String @map("prefix")
|
||||
accessKeyId String @map("access_key_id")
|
||||
secretAccessKey String @map("secret_access_key")
|
||||
region String @map("region")
|
||||
endpoint String? @map("endpoint")
|
||||
forcePathStyle Boolean @map("force_path_style")
|
||||
|
||||
// Integration Config
|
||||
nextSyncAt DateTime? @map("next_sync_at")
|
||||
lastSyncAt DateTime? @map("last_sync_at")
|
||||
enabled Boolean
|
||||
exportFrequency String @map("export_frequency")
|
||||
fileType BlobStorageIntegrationFileType @default(CSV) @map("file_type")
|
||||
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime @default(now()) @updatedAt @map("updated_at")
|
||||
|
||||
@@map("blob_storage_integrations")
|
||||
}
|
||||
|
||||
enum BlobStorageIntegrationFileType {
|
||||
JSON
|
||||
CSV
|
||||
JSONL
|
||||
|
||||
@@map("BlobStorageIntegrationFileType")
|
||||
}
|
||||
|
||||
enum BlobStorageIntegrationType {
|
||||
S3
|
||||
S3_COMPATIBLE
|
||||
AZURE_BLOB_STORAGE
|
||||
|
||||
@@map("BlobStorageIntegrationType")
|
||||
}
|
||||
|
||||
model BatchExport {
|
||||
id String @id @default(cuid())
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
@@ -879,7 +982,7 @@ model BatchExport {
|
||||
}
|
||||
|
||||
model Media {
|
||||
id String @id @default(cuid())
|
||||
id String
|
||||
sha256Hash String @map("sha_256_hash") @db.Char(44)
|
||||
projectId String @map("project_id")
|
||||
project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
|
||||
@@ -895,6 +998,7 @@ model Media {
|
||||
TraceMedia TraceMedia[]
|
||||
ObservationMedia ObservationMedia[]
|
||||
|
||||
@@unique([projectId, id])
|
||||
@@unique([projectId, sha256Hash])
|
||||
@@map("media")
|
||||
}
|
||||
@@ -906,11 +1010,12 @@ model TraceMedia {
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime @default(now()) @updatedAt @map("updated_at")
|
||||
mediaId String @map("media_id")
|
||||
media Media @relation(fields: [mediaId], references: [id], onDelete: Cascade)
|
||||
media Media @relation(fields: [mediaId, projectId], references: [id, projectId], onDelete: Cascade)
|
||||
traceId String @map("trace_id")
|
||||
field String @map("field")
|
||||
|
||||
@@unique([projectId, traceId, mediaId, field])
|
||||
@@index([projectId, mediaId])
|
||||
@@map("trace_media")
|
||||
}
|
||||
|
||||
@@ -921,27 +1026,17 @@ model ObservationMedia {
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime @default(now()) @updatedAt @map("updated_at")
|
||||
mediaId String @map("media_id")
|
||||
media Media @relation(fields: [mediaId], references: [id], onDelete: Cascade)
|
||||
media Media @relation(fields: [mediaId, projectId], references: [id, projectId], onDelete: Cascade)
|
||||
traceId String @map("trace_id")
|
||||
observationId String @map("observation_id")
|
||||
field String @map("field")
|
||||
|
||||
@@unique([projectId, traceId, observationId, mediaId, field])
|
||||
@@index([projectId, observationId])
|
||||
@@index([projectId, mediaId])
|
||||
@@map("observation_media")
|
||||
}
|
||||
|
||||
model QueueBackUp {
|
||||
id String @id @default(cuid())
|
||||
projectId String? @map("project_id")
|
||||
queueName String @map("queue_name")
|
||||
content Json
|
||||
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
|
||||
@@map("queue_backups")
|
||||
}
|
||||
|
||||
model BillingMeterBackup {
|
||||
// unique
|
||||
stripeCustomerId String @map("stripe_customer_id")
|
||||
@@ -964,3 +1059,128 @@ model BillingMeterBackup {
|
||||
@@index([stripeCustomerId, meterId, startTime, endTime])
|
||||
@@map("billing_meter_backups")
|
||||
}
|
||||
|
||||
model LlmSchema {
|
||||
id String @id @default(cuid())
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime @default(now()) @updatedAt @map("updated_at")
|
||||
|
||||
projectId String @map("project_id")
|
||||
project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
|
||||
|
||||
name String @map("name")
|
||||
description String @map("description")
|
||||
schema Json @map("schema") @db.Json
|
||||
|
||||
@@unique([projectId, name])
|
||||
@@map("llm_schemas")
|
||||
}
|
||||
|
||||
model LlmTool {
|
||||
id String @id @default(cuid())
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime @default(now()) @updatedAt @map("updated_at")
|
||||
|
||||
projectId String @map("project_id")
|
||||
project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
|
||||
|
||||
name String @map("name")
|
||||
description String @map("description")
|
||||
parameters Json @map("parameters") @db.Json
|
||||
|
||||
@@unique([projectId, name])
|
||||
@@map("llm_tools")
|
||||
}
|
||||
|
||||
model Dashboard {
|
||||
id String @id @default(cuid())
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime @default(now()) @updatedAt @map("updated_at")
|
||||
|
||||
createdBy String? @map("created_by")
|
||||
createdByUser User? @relation("CreatedByUser", fields: [createdBy], references: [id], onDelete: SetNull)
|
||||
updatedBy String? @map("updated_by")
|
||||
updatedByUser User? @relation("UpdatedByUser", fields: [updatedBy], references: [id], onDelete: SetNull)
|
||||
|
||||
// Optional to account for Langfuse-managed dashboards
|
||||
projectId String? @map("project_id")
|
||||
project Project? @relation(fields: [projectId], references: [id], onDelete: Cascade)
|
||||
|
||||
name String @map("name")
|
||||
description String @map("description")
|
||||
|
||||
definition Json @map("definition")
|
||||
|
||||
@@map("dashboards")
|
||||
}
|
||||
|
||||
enum DashboardWidgetViews {
|
||||
TRACES
|
||||
OBSERVATIONS
|
||||
SCORES_NUMERIC
|
||||
SCORES_CATEGORICAL
|
||||
}
|
||||
|
||||
enum DashboardWidgetChartType {
|
||||
LINE_TIME_SERIES
|
||||
BAR_TIME_SERIES
|
||||
HORIZONTAL_BAR
|
||||
VERTICAL_BAR
|
||||
PIE
|
||||
NUMBER
|
||||
}
|
||||
|
||||
model DashboardWidget {
|
||||
id String @id @default(cuid())
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime @default(now()) @updatedAt @map("updated_at")
|
||||
|
||||
createdBy String? @map("created_by")
|
||||
createdByUser User? @relation("CreatedByUser", fields: [createdBy], references: [id], onDelete: SetNull)
|
||||
updatedBy String? @map("updated_by")
|
||||
updatedByUser User? @relation("UpdatedByUser", fields: [updatedBy], references: [id], onDelete: SetNull)
|
||||
|
||||
// Optional to account for Langfuse-managed dashboards
|
||||
projectId String? @map("project_id")
|
||||
project Project? @relation(fields: [projectId], references: [id], onDelete: Cascade)
|
||||
|
||||
name String @map("name")
|
||||
description String @map("description")
|
||||
|
||||
view DashboardWidgetViews @map("view")
|
||||
dimensions Json @map("dimensions")
|
||||
metrics Json @map("metrics")
|
||||
filters Json @map("filters")
|
||||
|
||||
chartType DashboardWidgetChartType @map("chart_type")
|
||||
chartConfig Json @map("chart_config")
|
||||
|
||||
@@map("dashboard_widgets")
|
||||
}
|
||||
|
||||
model TableViewPreset {
|
||||
id String @id @default(cuid())
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime @default(now()) @updatedAt @map("updated_at")
|
||||
|
||||
projectId String @map("project_id")
|
||||
project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
|
||||
|
||||
name String @map("name")
|
||||
tableName String @map("table_name")
|
||||
|
||||
createdBy String? @map("created_by")
|
||||
createdByUser User? @relation("CreatedByUser", fields: [createdBy], references: [id], onDelete: SetNull)
|
||||
updatedBy String? @map("updated_by")
|
||||
updatedByUser User? @relation("UpdatedByUser", fields: [updatedBy], references: [id], onDelete: SetNull)
|
||||
|
||||
// view configuration
|
||||
filters Json @map("filters")
|
||||
columnOrder Json @map("column_order")
|
||||
columnVisibility Json @map("column_visibility")
|
||||
searchQuery String? @map("search_query")
|
||||
orderBy Json? @map("order_by")
|
||||
|
||||
@@unique([projectId, tableName, name])
|
||||
@@map("table_view_presets")
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import { ModelUsageUnit } from "../src";
|
||||
import { getDisplaySecretKey, hashSecretKey, logger } from "../src/server";
|
||||
import { encrypt } from "../src/encryption";
|
||||
import { redis } from "../src/server/redis/redis";
|
||||
import { randomUUID } from "crypto";
|
||||
|
||||
const LOAD_TRACE_VOLUME = 10_000;
|
||||
|
||||
@@ -72,6 +73,9 @@ async function main() {
|
||||
where: { id: seedOrgId },
|
||||
update: {
|
||||
name: "Seed Org",
|
||||
cloudConfig: {
|
||||
plan: "Team",
|
||||
},
|
||||
},
|
||||
create: {
|
||||
id: seedOrgId,
|
||||
@@ -177,6 +181,7 @@ async function main() {
|
||||
publicKey: seedApiKey.public,
|
||||
hashedSecretKey: await hashSecretKey(seedApiKey.secret),
|
||||
displaySecretKey: getDisplaySecretKey(seedApiKey.secret),
|
||||
scope: "PROJECT",
|
||||
project: {
|
||||
connect: {
|
||||
id: project1.id,
|
||||
@@ -238,6 +243,7 @@ async function main() {
|
||||
publicKey: secondKey.public,
|
||||
hashedSecretKey: await hashSecretKey(secondKey.secret),
|
||||
displaySecretKey: getDisplaySecretKey(secondKey.secret),
|
||||
scope: "PROJECT",
|
||||
project: {
|
||||
connect: {
|
||||
id: project2.id,
|
||||
@@ -371,6 +377,48 @@ async function main() {
|
||||
});
|
||||
|
||||
await createDatasets(project1, project2, observations);
|
||||
|
||||
await createDashboardsAndWidgets([project1, project2]);
|
||||
|
||||
await prisma.llmSchema.createMany({
|
||||
data: [
|
||||
{
|
||||
projectId: project1.id,
|
||||
name: "get_weather",
|
||||
description: "Fetches weather in Celsius for a given location",
|
||||
schema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
location: {
|
||||
type: "string",
|
||||
description: "The city and state, e.g. San Francisco, CA",
|
||||
},
|
||||
unit: {
|
||||
type: "string",
|
||||
enum: ["celsius", "fahrenheit"],
|
||||
},
|
||||
},
|
||||
required: ["location", "unit"],
|
||||
},
|
||||
},
|
||||
{
|
||||
projectId: project1.id,
|
||||
name: "calculator",
|
||||
description: "Performs basic arithmetic calculations",
|
||||
schema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
expression: {
|
||||
type: "string",
|
||||
description:
|
||||
"The mathematical expression to evaluate, e.g. '2 + 2'",
|
||||
},
|
||||
},
|
||||
required: ["expression"],
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -388,6 +436,85 @@ main()
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
async function createDashboardsAndWidgets(projects: Project[]) {
|
||||
logger.info("Creating dashboards and widgets");
|
||||
|
||||
// Process each project
|
||||
for (const project of projects) {
|
||||
const widget = await prisma.dashboardWidget.upsert({
|
||||
where: { id: "cabc" },
|
||||
create: {
|
||||
id: "cabc",
|
||||
projectId: project.id,
|
||||
name: "Trace Counts",
|
||||
description: "Trace Counts by Name Over Time",
|
||||
view: "TRACES",
|
||||
dimensions: [{ field: "name" }],
|
||||
metrics: [{ measure: "count", agg: "count" }],
|
||||
filters: [],
|
||||
chartType: "BAR_TIME_SERIES",
|
||||
chartConfig: {
|
||||
type: "BAR_TIME_SERIES",
|
||||
},
|
||||
},
|
||||
update: {},
|
||||
});
|
||||
|
||||
const widget2 = await prisma.dashboardWidget.upsert({
|
||||
where: { id: "cdef" },
|
||||
create: {
|
||||
id: "cdef",
|
||||
projectId: project.id,
|
||||
name: "Observation Latencies by Model",
|
||||
description: "p95 Observation Latencies by Model Name",
|
||||
view: "OBSERVATIONS",
|
||||
dimensions: [{ field: "providedModelName" }],
|
||||
metrics: [{ measure: "count", agg: "sum" }],
|
||||
filters: [],
|
||||
chartType: "LINE_TIME_SERIES",
|
||||
chartConfig: {
|
||||
type: "LINE_TIME_SERIES",
|
||||
},
|
||||
},
|
||||
update: {},
|
||||
});
|
||||
|
||||
// Create a dashboard with multiple widgets
|
||||
await prisma.dashboard.upsert({
|
||||
where: { id: "seed-dashboard" },
|
||||
create: {
|
||||
id: "seed-dashboard",
|
||||
projectId: project.id,
|
||||
name: "Performance Overview",
|
||||
description: "Dashboard with various performance metrics",
|
||||
definition: {
|
||||
widgets: [
|
||||
{
|
||||
type: "widget",
|
||||
id: randomUUID(),
|
||||
widgetId: widget.id,
|
||||
x: 0,
|
||||
y: 0,
|
||||
x_size: 6,
|
||||
y_size: 6,
|
||||
},
|
||||
{
|
||||
type: "widget",
|
||||
id: randomUUID(),
|
||||
widgetId: widget2.id,
|
||||
x: 6,
|
||||
y: 0,
|
||||
x_size: 6,
|
||||
y_size: 6,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
update: {},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export async function createDatasets(
|
||||
project1: {
|
||||
id: string;
|
||||
@@ -727,6 +854,7 @@ function createObjects(
|
||||
source: "API",
|
||||
projectId,
|
||||
dataType: ScoreDataType.NUMERIC,
|
||||
metadata: {},
|
||||
},
|
||||
]
|
||||
: []),
|
||||
@@ -742,6 +870,7 @@ function createObjects(
|
||||
dataType: ScoreDataType.CATEGORICAL,
|
||||
stringValue:
|
||||
Math.floor(Math.random() * 2) === 1 ? "Fully" : "Partially",
|
||||
metadata: {},
|
||||
},
|
||||
]
|
||||
: []),
|
||||
|
||||
@@ -27,6 +27,9 @@ const prepareProjectsAndApiKeys = async (
|
||||
create: {
|
||||
id: orgId,
|
||||
name: `Organization for ${projectId}`,
|
||||
cloudConfig: {
|
||||
plan: "Team",
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -55,6 +58,7 @@ const prepareProjectsAndApiKeys = async (
|
||||
publicKey: `pk-${Math.random().toString(36).substr(2, 9)}`,
|
||||
hashedSecretKey: sk,
|
||||
displaySecretKey: getDisplaySecretKey(sk),
|
||||
scope: "PROJECT",
|
||||
project: {
|
||||
connect: {
|
||||
id: projectId,
|
||||
|
||||
@@ -63,7 +63,7 @@ export const prepareClickhouse = async (
|
||||
toDateTime(now() - randUniform(0, ${opts.numberOfDays} * 24 * 60 * 60)) AS timestamp,
|
||||
concat('name_', toString(rand() % 100)) AS name,
|
||||
concat('user_id_', toInt64(randExponential(1 / 100))) AS user_id,
|
||||
map('key', 'value') AS metadata,
|
||||
map('prototype', 'test') AS metadata,
|
||||
concat('release_', toString(randUniform(0, 100))) AS release,
|
||||
concat('version_', toString(randUniform(0, 100))) AS version,
|
||||
'${projectId}' AS project_id,
|
||||
@@ -92,14 +92,14 @@ export const prepareClickhouse = async (
|
||||
toDateTime(now() - randUniform(0, ${opts.numberOfDays} * 24 * 60 * 60)) AS start_time,
|
||||
addSeconds(start_time, if(rand() < 0.6, floor(randUniform(0, 20)), floor(randUniform(0, 3600)))) AS end_time,
|
||||
concat('name', toString(rand() % 100)) AS name,
|
||||
map('key', 'value') AS metadata,
|
||||
map('prototype', 'test') AS metadata,
|
||||
if(randUniform(0, 1) < 0.9, 'DEFAULT', if(randUniform(0, 1) < 0.5, 'ERROR', if(randUniform(0, 1) < 0.5, 'DEBUG', 'WARNING'))) AS level,
|
||||
'status_message' AS status_message,
|
||||
'version' AS version,
|
||||
repeat('input', toInt64(randExponential(1 / 100))) AS input,
|
||||
repeat('output', toInt64(randExponential(1 / 100))) AS output,
|
||||
case
|
||||
when number % 2 = 0 then 'clause-3-haiku-20230407'
|
||||
when number % 2 = 0 then 'claude-3-haiku-20230407'
|
||||
else 'gpt-4'
|
||||
end as provided_model_name,
|
||||
case
|
||||
@@ -141,15 +141,15 @@ export const prepareClickhouse = async (
|
||||
FROM numbers(${observationsPerProject});
|
||||
`;
|
||||
|
||||
console.log(observationsQuery);
|
||||
|
||||
const scoresQuery = `
|
||||
INSERT INTO scores
|
||||
SELECT toString(floor(randUniform(0, 100))) AS id,
|
||||
SELECT toString(number) AS id,
|
||||
toDateTime(now() - randUniform(0, ${opts.numberOfDays} * 24 * 60 * 60)) AS timestamp,
|
||||
'${projectId}' AS project_id,
|
||||
'default' AS environment,
|
||||
toString(floor(randUniform(0, ${tracesPerProject}))) AS trace_id,
|
||||
NULL AS session_id,
|
||||
NULL AS dataset_run_id,
|
||||
if(
|
||||
rand() > 0.9,
|
||||
toString(floor(randUniform(0, ${observationsPerProject}))),
|
||||
@@ -159,6 +159,7 @@ export const prepareClickhouse = async (
|
||||
randUniform(0, 100) as value,
|
||||
'API' as source,
|
||||
'comment' as comment,
|
||||
map('prototype', 'test') AS metadata,
|
||||
toString(rand() % 100) as author_user_id,
|
||||
toString(rand() % 100) as config_id,
|
||||
if (rand() < 0.33, 'NUMERIC', if (rand() < 0.5, 'CATEGORICAL', 'BOOLEAN')) as data_type,
|
||||
@@ -199,6 +200,48 @@ export const prepareClickhouse = async (
|
||||
project_id: string;
|
||||
}>();
|
||||
|
||||
const sessionsToScore = sessionData
|
||||
.filter(() => Math.random() < 0.5)
|
||||
.slice(0, Math.min(500, sessionData.length));
|
||||
|
||||
if (sessionsToScore.length > 0) {
|
||||
// Generate session scores query with specific session IDs
|
||||
const sessionScoresQuery = `
|
||||
INSERT INTO scores
|
||||
SELECT
|
||||
concat('session-', toString(number)) AS id,
|
||||
toDateTime(now() - randUniform(0, ${opts.numberOfDays} * 24 * 60 * 60)) AS timestamp,
|
||||
'${projectId}' AS project_id,
|
||||
'default' AS environment,
|
||||
NULL AS trace_id,
|
||||
arrayElement(['${sessionsToScore.map((s) => s.session_id).join("','")}'], 1 + (number % ${sessionsToScore.length})) AS session_id,
|
||||
NULL AS dataset_run_id,
|
||||
NULL AS observation_id,
|
||||
concat('session_quality_', toString(rand() % 10)) AS name,
|
||||
randUniform(0, 100) AS value,
|
||||
'API' AS source,
|
||||
'Session-level assessment score' AS comment,
|
||||
map('key', 'value') AS metadata,
|
||||
toString(rand() % 100) AS author_user_id,
|
||||
toString(rand() % 100) AS config_id,
|
||||
if(rand() < 0.33, 'NUMERIC', if(rand() < 0.5, 'CATEGORICAL', 'BOOLEAN')) AS data_type,
|
||||
toString(rand() % 100) AS string_value,
|
||||
NULL AS queue_id,
|
||||
timestamp AS created_at,
|
||||
timestamp AS updated_at,
|
||||
timestamp AS event_ts,
|
||||
0 AS is_deleted
|
||||
FROM numbers(${sessionsToScore.length})
|
||||
`;
|
||||
|
||||
await clickhouseClient().command({
|
||||
query: sessionScoresQuery,
|
||||
clickhouse_settings: {
|
||||
wait_end_of_query: 1,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
const idProjectIdCombinations = sessionData.map((session) => ({
|
||||
id: session.session_id,
|
||||
projectId: session.project_id,
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
export * from "./observations";
|
||||
export * from "./traces";
|
||||
export * from "./scores";
|
||||
export * from "./table-view-presets";
|
||||
@@ -0,0 +1,76 @@
|
||||
import z from "zod";
|
||||
import { jsonSchema } from "../utils/zod";
|
||||
import { MetadataDomain } from "./traces";
|
||||
|
||||
export const ObservationType = {
|
||||
SPAN: "SPAN",
|
||||
EVENT: "EVENT",
|
||||
GENERATION: "GENERATION",
|
||||
} as const;
|
||||
export const ObservationTypeDomain = z.enum(["SPAN", "EVENT", "GENERATION"]);
|
||||
export type ObservationType = z.infer<typeof ObservationTypeDomain>;
|
||||
|
||||
export const ObservationLevel = {
|
||||
DEBUG: "DEBUG",
|
||||
DEFAULT: "DEFAULT",
|
||||
WARNING: "WARNING",
|
||||
ERROR: "ERROR",
|
||||
} as const;
|
||||
export const ObservationLevelDomain = z.enum([
|
||||
"DEBUG",
|
||||
"DEFAULT",
|
||||
"WARNING",
|
||||
"ERROR",
|
||||
]);
|
||||
export type ObservationLevelType = z.infer<typeof ObservationLevelDomain>;
|
||||
|
||||
export const ObservationDomain = z.object({
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
timestamp: z.date(),
|
||||
environment: z.string(),
|
||||
tags: z.array(z.string()),
|
||||
});
|
||||
export type ObservationDomain = z.infer<typeof ObservationDomain>;
|
||||
|
||||
export const ObservationSchema = z.object({
|
||||
id: z.string(),
|
||||
traceId: z.string().nullable(),
|
||||
projectId: z.string(),
|
||||
environment: z.string(),
|
||||
type: ObservationTypeDomain,
|
||||
startTime: z.date(),
|
||||
endTime: z.date().nullable(),
|
||||
name: z.string().nullable(),
|
||||
metadata: MetadataDomain,
|
||||
parentObservationId: z.string().nullable(),
|
||||
level: ObservationLevelDomain,
|
||||
statusMessage: z.string().nullable(),
|
||||
version: z.string().nullable(),
|
||||
createdAt: z.date(),
|
||||
updatedAt: z.date(),
|
||||
model: z.string().nullable(),
|
||||
internalModelId: z.string().nullable(),
|
||||
modelParameters: jsonSchema.nullable(),
|
||||
input: jsonSchema.nullable(),
|
||||
output: jsonSchema.nullable(),
|
||||
completionStartTime: z.date().nullable(),
|
||||
promptId: z.string().nullable(),
|
||||
promptName: z.string().nullable(),
|
||||
promptVersion: z.number().nullable(),
|
||||
latency: z.number().nullable(),
|
||||
timeToFirstToken: z.number().nullable(),
|
||||
usageDetails: z.record(z.string(), z.number()),
|
||||
costDetails: z.record(z.string(), z.number()),
|
||||
providedCostDetails: z.record(z.string(), z.number()),
|
||||
// aggregated data from cost_details
|
||||
inputCost: z.number().nullable(),
|
||||
outputCost: z.number().nullable(),
|
||||
totalCost: z.number().nullable(),
|
||||
// aggregated data from usage_details
|
||||
inputUsage: z.number(),
|
||||
outputUsage: z.number(),
|
||||
totalUsage: z.number(),
|
||||
});
|
||||
|
||||
export type Observation = z.infer<typeof ObservationSchema>;
|
||||
@@ -0,0 +1,37 @@
|
||||
import { ScoreDataType } from "@prisma/client";
|
||||
import z from "zod";
|
||||
import { MetadataDomain } from "./traces";
|
||||
|
||||
export const ScoreSource = {
|
||||
ANNOTATION: "ANNOTATION",
|
||||
API: "API",
|
||||
EVAL: "EVAL",
|
||||
} as const;
|
||||
|
||||
export const ScoreSourceDomain = z.enum(["ANNOTATION", "API", "EVAL"]);
|
||||
export type ScoreSourceType = z.infer<typeof ScoreSourceDomain>;
|
||||
|
||||
export const ScoreSchema = z.object({
|
||||
id: z.string(),
|
||||
timestamp: z.date(),
|
||||
projectId: z.string(),
|
||||
environment: z.string(),
|
||||
name: z.string(),
|
||||
value: z.number().nullable(),
|
||||
source: ScoreSourceDomain,
|
||||
authorUserId: z.string().nullable(),
|
||||
comment: z.string().nullable(),
|
||||
traceId: z.string().nullable(),
|
||||
sessionId: z.string().nullable(),
|
||||
datasetRunId: z.string().nullable(),
|
||||
metadata: MetadataDomain,
|
||||
observationId: z.string().nullable(),
|
||||
configId: z.string().nullable(),
|
||||
stringValue: z.string().nullable(),
|
||||
queueId: z.string().nullable(),
|
||||
createdAt: z.date(),
|
||||
updatedAt: z.date(),
|
||||
dataType: z.nativeEnum(ScoreDataType),
|
||||
});
|
||||
|
||||
export type ScoreDomain = z.infer<typeof ScoreSchema>;
|
||||
@@ -0,0 +1,28 @@
|
||||
import { singleFilter } from "../interfaces/filters";
|
||||
import { orderBy } from "../interfaces/orderBy";
|
||||
import z from "zod";
|
||||
|
||||
export enum TableViewPresetTableName {
|
||||
Traces = "traces",
|
||||
Observations = "observations",
|
||||
Scores = "scores",
|
||||
Sessions = "sessions",
|
||||
Datasets = "datasets",
|
||||
}
|
||||
|
||||
const TableViewPresetDomainSchema = z.object({
|
||||
id: z.string(),
|
||||
projectId: z.string().nullable(),
|
||||
createdAt: z.date(),
|
||||
updatedAt: z.date(),
|
||||
createdBy: z.string().nullable(),
|
||||
name: z.string(),
|
||||
tableName: z.nativeEnum(TableViewPresetTableName),
|
||||
filters: z.array(singleFilter),
|
||||
columnOrder: z.array(z.string()),
|
||||
columnVisibility: z.record(z.string(), z.boolean()),
|
||||
searchQuery: z.string().optional(),
|
||||
orderBy: orderBy,
|
||||
});
|
||||
|
||||
export type TableViewPresetDomain = z.infer<typeof TableViewPresetDomainSchema>;
|
||||
@@ -0,0 +1,32 @@
|
||||
import z from "zod";
|
||||
import { jsonSchema, jsonSchemaNullable } from "../utils/zod";
|
||||
|
||||
export const MetadataDomain = z.record(
|
||||
z.string(),
|
||||
jsonSchemaNullable.or(z.undefined()),
|
||||
);
|
||||
|
||||
export type MetadataDomain = z.infer<typeof MetadataDomain>;
|
||||
|
||||
// to be used across the application in frontend and backend.
|
||||
export const TraceDomain = z.object({
|
||||
id: z.string(),
|
||||
name: z.string().nullable(),
|
||||
timestamp: z.date(),
|
||||
environment: z.string(),
|
||||
tags: z.array(z.string()),
|
||||
bookmarked: z.boolean(),
|
||||
public: z.boolean(),
|
||||
release: z.string().nullable(),
|
||||
version: z.string().nullable(),
|
||||
input: jsonSchema.nullable(),
|
||||
output: jsonSchema.nullable(),
|
||||
metadata: MetadataDomain,
|
||||
createdAt: z.date(),
|
||||
updatedAt: z.date(),
|
||||
sessionId: z.string().nullable(),
|
||||
userId: z.string().nullable(),
|
||||
projectId: z.string(),
|
||||
});
|
||||
|
||||
export type TraceDomain = z.infer<typeof TraceDomain>;
|
||||
@@ -2,6 +2,7 @@ import { z } from "zod";
|
||||
import { removeEmptyEnvVariables } from "./utils/environment";
|
||||
|
||||
const EnvSchema = z.object({
|
||||
NEXT_PUBLIC_LANGFUSE_CLOUD_REGION: z.string().optional(),
|
||||
NODE_ENV: z
|
||||
.enum(["development", "test", "production"])
|
||||
.default("development"),
|
||||
@@ -10,7 +11,7 @@ const EnvSchema = z.object({
|
||||
REDIS_PORT: z.coerce
|
||||
.number({
|
||||
description:
|
||||
".env files convert numbers to strings, therefoore we have to enforce them to be numbers",
|
||||
".env files convert numbers to strings, therefore we have to enforce them to be numbers",
|
||||
})
|
||||
.positive()
|
||||
.max(65536, `options.port should be >= 0 and < 65536`)
|
||||
@@ -37,6 +38,8 @@ const EnvSchema = z.object({
|
||||
CLICKHOUSE_DB: z.string().default("default"),
|
||||
CLICKHOUSE_USER: z.string(),
|
||||
CLICKHOUSE_PASSWORD: z.string(),
|
||||
CLICKHOUSE_KEEP_ALIVE_IDLE_SOCKET_TTL: z.coerce.number().int().default(9000),
|
||||
CLICKHOUSE_MAX_OPEN_CONNECTIONS: z.coerce.number().int().default(25),
|
||||
|
||||
LANGFUSE_INGESTION_QUEUE_DELAY_MS: z.coerce
|
||||
.number()
|
||||
@@ -50,10 +53,7 @@ const EnvSchema = z.object({
|
||||
ENABLE_AWS_CLOUDWATCH_METRIC_PUBLISHING: z
|
||||
.enum(["true", "false"])
|
||||
.default("false"),
|
||||
LANGFUSE_S3_CONCURRENT_WRITES: z.coerce
|
||||
.number()
|
||||
.positive()
|
||||
.default(50),
|
||||
LANGFUSE_S3_CONCURRENT_WRITES: z.coerce.number().positive().default(50),
|
||||
LANGFUSE_S3_EVENT_UPLOAD_BUCKET: z.string({
|
||||
required_error: "Langfuse requires a bucket name for S3 Event Uploads.",
|
||||
}),
|
||||
@@ -65,7 +65,18 @@ const EnvSchema = z.object({
|
||||
LANGFUSE_S3_EVENT_UPLOAD_FORCE_PATH_STYLE: z
|
||||
.enum(["true", "false"])
|
||||
.default("false"),
|
||||
LANGFUSE_S3_MEDIA_UPLOAD_BUCKET: z.string().optional(),
|
||||
LANGFUSE_S3_MEDIA_UPLOAD_PREFIX: z.string().default(""),
|
||||
LANGFUSE_S3_MEDIA_UPLOAD_REGION: z.string().optional(),
|
||||
LANGFUSE_S3_MEDIA_UPLOAD_ENDPOINT: z.string().optional(),
|
||||
LANGFUSE_S3_MEDIA_UPLOAD_ACCESS_KEY_ID: z.string().optional(),
|
||||
LANGFUSE_S3_MEDIA_UPLOAD_SECRET_ACCESS_KEY: z.string().optional(),
|
||||
LANGFUSE_S3_MEDIA_UPLOAD_FORCE_PATH_STYLE: z
|
||||
.enum(["true", "false"])
|
||||
.default("false"),
|
||||
LANGFUSE_USE_AZURE_BLOB: z.enum(["true", "false"]).default("false"),
|
||||
LANGFUSE_USE_GOOGLE_CLOUD_STORAGE: z.enum(["true", "false"]).default("false"),
|
||||
LANGFUSE_GOOGLE_CLOUD_STORAGE_CREDENTIALS: z.string().optional(),
|
||||
STRIPE_SECRET_KEY: z.string().optional(),
|
||||
|
||||
LANGFUSE_S3_CORE_DATA_EXPORT_IS_ENABLED: z
|
||||
@@ -75,9 +86,13 @@ const EnvSchema = z.object({
|
||||
.enum(["true", "false"])
|
||||
.default("false"),
|
||||
|
||||
LANGFUSE_CUSTOM_SSO_EMAIL_CLAIM: z.string().default('email'),
|
||||
LANGFUSE_CUSTOM_SSO_NAME_CLAIM: z.string().default('name'),
|
||||
LANGFUSE_CUSTOM_SSO_SUB_CLAIM: z.string().default('sub'),
|
||||
LANGFUSE_CUSTOM_SSO_EMAIL_CLAIM: z.string().default("email"),
|
||||
LANGFUSE_CUSTOM_SSO_NAME_CLAIM: z.string().default("name"),
|
||||
LANGFUSE_CUSTOM_SSO_SUB_CLAIM: z.string().default("sub"),
|
||||
LANGFUSE_API_TRACE_OBSERVATIONS_SIZE_LIMIT_BYTES: z.coerce
|
||||
.number()
|
||||
.default(80e6), // 80MB
|
||||
LANGFUSE_CLICKHOUSE_DELETION_TIMEOUT_MS: z.coerce.number().default(240_000), // 4 minutes
|
||||
});
|
||||
|
||||
export const env: z.infer<typeof EnvSchema> =
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
import { BaseError } from "./BaseError";
|
||||
|
||||
export class LangfuseConflictError extends BaseError {
|
||||
constructor(description = "Conflict") {
|
||||
super("LangfuseConflictError", 409, description, true);
|
||||
}
|
||||
}
|
||||
@@ -6,3 +6,4 @@ export { ForbiddenError } from "./ForbiddenError";
|
||||
export { MethodNotAllowedError } from "./MethodNotAllowedError";
|
||||
export { ApiError } from "./ApiError";
|
||||
export { InternalServerError } from "./InternalServerError";
|
||||
export { LangfuseConflictError } from "./ConflictError";
|
||||
|
||||
@@ -25,13 +25,33 @@ const BooleanData = z.object({
|
||||
dataType: z.literal("BOOLEAN"),
|
||||
});
|
||||
|
||||
const ScoreTargetTrace = z.object({
|
||||
type: z.literal("trace"),
|
||||
traceId: z.string(),
|
||||
observationId: z.string().optional(),
|
||||
});
|
||||
|
||||
const ScoreTargetSession = z.object({
|
||||
type: z.literal("session"),
|
||||
sessionId: z.string(),
|
||||
});
|
||||
|
||||
// Your existing ScoreTarget remains the same, but can now use these components
|
||||
const ScoreTarget = z.discriminatedUnion("type", [
|
||||
ScoreTargetTrace,
|
||||
ScoreTargetSession,
|
||||
]);
|
||||
|
||||
export type ScoreTargetTrace = z.infer<typeof ScoreTargetTrace>;
|
||||
export type ScoreTargetSession = z.infer<typeof ScoreTargetSession>;
|
||||
export type ScoreTarget = z.infer<typeof ScoreTarget>;
|
||||
|
||||
const CreateAnnotationScoreBase = z.object({
|
||||
name: z.string(),
|
||||
projectId: z.string(),
|
||||
environment: z.string().default("default"),
|
||||
traceId: z.string(),
|
||||
scoreTarget: ScoreTarget,
|
||||
configId: z.string().optional(),
|
||||
observationId: z.string().optional(),
|
||||
comment: z.string().nullish(),
|
||||
queueId: z.string().nullish(),
|
||||
});
|
||||
|
||||
@@ -10,6 +10,7 @@ export enum BatchActionType {
|
||||
}
|
||||
|
||||
const ActionIdSchema = z.enum([
|
||||
"score-delete",
|
||||
"trace-delete",
|
||||
"trace-add-to-annotation-queue",
|
||||
]);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user