diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 000000000..8e0dbd5f9
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,5 @@
+{
+ "[mdx]": {
+ "editor.formatOnSave": false
+ }
+}
diff --git a/README.md b/README.md
index 4cbe0750c..775fa584f 100644
--- a/README.md
+++ b/README.md
@@ -1,22 +1,16 @@
-# Mintlify Starter Kit
+# LangWatch and LangEvals Documentation
-Click on `Use this template` to copy the Mintlify starter kit. The starter kit contains examples including
-
-- Guide pages
-- Navigation
-- Customizations
-- API Reference pages
-- Use of popular components
+This is the documentation repository for the [LangWatch](https://github.com/langwatch/langwatch) and [LangEvals](https://github.com/langwatch/langevals) projects.
### Development
-Install the [Mintlify CLI](https://www.npmjs.com/package/mintlify) to preview the documentation changes locally. To install, use the following command
+Install the [Mintlify CLI](https://www.npmjs.com/package/mintlify) to preview the documentation changes locally. To install, use the following command:
```
npm i -g mintlify
```
-Run the following command at the root of your documentation (where mint.json is)
+Run the following command:
```
mintlify dev
@@ -24,9 +18,5 @@ mintlify dev
### Publishing Changes
-Install our Github App to auto propagate changes from your repo to your deployment. Changes will be deployed to production automatically after pushing to the default branch. Find the link to install on your dashboard.
-
-#### Troubleshooting
+Install our Github App to auto propagate changes from your repo to your deployment. Changes will be deployed to production automatically after pushing to the default branch. Find the link to install on your dashboard.
-- Mintlify dev isn't running - Run `mintlify install` it'll re-install dependencies.
-- Page loads as a 404 - Make sure you are running in a folder with `mint.json`
diff --git a/api-reference/annotations/create-annotation-trace.mdx b/api-reference/annotations/create-annotation-trace.mdx
new file mode 100644
index 000000000..bfb58ada6
--- /dev/null
+++ b/api-reference/annotations/create-annotation-trace.mdx
@@ -0,0 +1,4 @@
+---
+title: 'Create annotation for single trace'
+openapi: 'POST /api/annotations/trace/{id}'
+---
diff --git a/api-reference/annotations/delete-annotation.mdx b/api-reference/annotations/delete-annotation.mdx
new file mode 100644
index 000000000..571b633c1
--- /dev/null
+++ b/api-reference/annotations/delete-annotation.mdx
@@ -0,0 +1,5 @@
+---
+title: 'Delete single annotation'
+openapi: 'DELETE /api/annotations/{id}'
+---
+
diff --git a/api-reference/annotations/get-all-annotations-trace.mdx b/api-reference/annotations/get-all-annotations-trace.mdx
new file mode 100644
index 000000000..d29463fcf
--- /dev/null
+++ b/api-reference/annotations/get-all-annotations-trace.mdx
@@ -0,0 +1,4 @@
+---
+title: 'Get annotationa for single trace'
+openapi: 'GET /api/annotations/trace/{id}'
+---
diff --git a/api-reference/annotations/get-annotation.mdx b/api-reference/annotations/get-annotation.mdx
new file mode 100644
index 000000000..e3216097f
--- /dev/null
+++ b/api-reference/annotations/get-annotation.mdx
@@ -0,0 +1,4 @@
+---
+title: 'Get annotations'
+openapi: 'GET /api/annotations'
+---
diff --git a/api-reference/annotations/get-single-annotation.mdx b/api-reference/annotations/get-single-annotation.mdx
new file mode 100644
index 000000000..da42bf778
--- /dev/null
+++ b/api-reference/annotations/get-single-annotation.mdx
@@ -0,0 +1,4 @@
+---
+title: 'Get single annotation'
+openapi: 'GET /api/annotations/{id}'
+---
diff --git a/api-reference/annotations/overview.mdx b/api-reference/annotations/overview.mdx
new file mode 100644
index 000000000..8c42de72e
--- /dev/null
+++ b/api-reference/annotations/overview.mdx
@@ -0,0 +1,26 @@
+---
+title: 'Overview'
+description: 'Annotations are used to annotate traces with additional information'
+---
+
+## Intro
+
+With the Annotations API, you can annotate traces with additional information. This is useful if you want to add additional information to a trace, such as a comment or a thumbs up/down reaction.
+
+## Authentication
+
+To make a call to the Annotations API, you will need to pass through your LangWatch API key in the header as `X-Auth-Token`. Your API key can be found on the setup page under settings.
+
+
+#### Allowed Methods
+
+- `GET /api/annotations` - Get a list of annotations
+- `GET /api/annotations/:id` - Get a single annotation
+- `DELETE /api/annotations/:id` - Delete a single annotation
+- `PATCH /api/annotations/:id` - Update a single annotation
+- `GET /api/annotations/trace/:id` - Get the annotations for a single trace
+- `POST /api/annotations/trace/:id` - Create an annotation for a single trace
+
+
+
+
diff --git a/api-reference/annotations/patch-annotation.mdx b/api-reference/annotations/patch-annotation.mdx
new file mode 100644
index 000000000..4e04358f9
--- /dev/null
+++ b/api-reference/annotations/patch-annotation.mdx
@@ -0,0 +1,5 @@
+---
+title: 'Patch single annotation'
+openapi: 'PATCH /api/annotations/{id}'
+---
+
diff --git a/api-reference/datasets/post-dataset-entries.mdx b/api-reference/datasets/post-dataset-entries.mdx
new file mode 100644
index 000000000..0357260c6
--- /dev/null
+++ b/api-reference/datasets/post-dataset-entries.mdx
@@ -0,0 +1,4 @@
+---
+title: 'Add entries to a dataset'
+openapi: 'POST /api/dataset/{slug}/entries'
+---
diff --git a/api-reference/endpoint/get.mdx b/api-reference/endpoint/get.mdx
deleted file mode 100644
index 56aa09ec1..000000000
--- a/api-reference/endpoint/get.mdx
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: 'Get Plants'
-openapi: 'GET /plants'
----
diff --git a/api-reference/openapi.json b/api-reference/openapi.json
deleted file mode 100644
index b1509be04..000000000
--- a/api-reference/openapi.json
+++ /dev/null
@@ -1,195 +0,0 @@
-{
- "openapi": "3.0.1",
- "info": {
- "title": "OpenAPI Plant Store",
- "description": "A sample API that uses a plant store as an example to demonstrate features in the OpenAPI specification",
- "license": {
- "name": "MIT"
- },
- "version": "1.0.0"
- },
- "servers": [
- {
- "url": "http://sandbox.mintlify.com"
- }
- ],
- "security": [
- {
- "bearerAuth": []
- }
- ],
- "paths": {
- "/plants": {
- "get": {
- "description": "Returns all plants from the system that the user has access to",
- "parameters": [
- {
- "name": "limit",
- "in": "query",
- "description": "The maximum number of results to return",
- "schema": {
- "type": "integer",
- "format": "int32"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "Plant response",
- "content": {
- "application/json": {
- "schema": {
- "type": "array",
- "items": {
- "$ref": "#/components/schemas/Plant"
- }
- }
- }
- }
- },
- "400": {
- "description": "Unexpected error",
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/Error"
- }
- }
- }
- }
- }
- },
- "post": {
- "description": "Creates a new plant in the store",
- "requestBody": {
- "description": "Plant to add to the store",
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/NewPlant"
- }
- }
- },
- "required": true
- },
- "responses": {
- "200": {
- "description": "plant response",
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/Plant"
- }
- }
- }
- },
- "400": {
- "description": "unexpected error",
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/Error"
- }
- }
- }
- }
- }
- }
- },
- "/plants/{id}": {
- "delete": {
- "description": "Deletes a single plant based on the ID supplied",
- "parameters": [
- {
- "name": "id",
- "in": "path",
- "description": "ID of plant to delete",
- "required": true,
- "schema": {
- "type": "integer",
- "format": "int64"
- }
- }
- ],
- "responses": {
- "204": {
- "description": "Plant deleted",
- "content": {}
- },
- "400": {
- "description": "unexpected error",
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/Error"
- }
- }
- }
- }
- }
- }
- }
- },
- "components": {
- "schemas": {
- "Plant": {
- "required": [
- "name"
- ],
- "type": "object",
- "properties": {
- "name": {
- "description": "The name of the plant",
- "type": "string"
- },
- "tag": {
- "description": "Tag to specify the type",
- "type": "string"
- }
- }
- },
- "NewPlant": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Plant"
- },
- {
- "required": [
- "id"
- ],
- "type": "object",
- "properties": {
- "id": {
- "description": "Identification number of the plant",
- "type": "integer",
- "format": "int64"
- }
- }
- }
- ]
- },
- "Error": {
- "required": [
- "error",
- "message"
- ],
- "type": "object",
- "properties": {
- "error": {
- "type": "integer",
- "format": "int32"
- },
- "message": {
- "type": "string"
- }
- }
- }
- },
- "securitySchemes": {
- "bearerAuth": {
- "type": "http",
- "scheme": "bearer"
- }
- }
- }
-}
\ No newline at end of file
diff --git a/api-reference/openapiLangWatch.json b/api-reference/openapiLangWatch.json
new file mode 100644
index 000000000..2d65e2301
--- /dev/null
+++ b/api-reference/openapiLangWatch.json
@@ -0,0 +1,1386 @@
+{
+ "openapi": "3.1.0",
+ "info": {
+ "title": "LangWatch API",
+ "version": "1.0.0",
+ "description": "LangWatch openapi spec"
+ },
+ "servers": [
+ {
+ "url": "https://app.langwatch.ai"
+ }
+ ],
+ "security": [
+ {
+ "api_key": []
+ }
+ ],
+ "paths": {
+ "/api/annotations": {
+ "get": {
+ "description": "Returns all annotations for project",
+ "responses": {
+ "200": {
+ "description": "Annotation response",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/Annotation"
+ }
+ }
+ }
+ }
+ },
+ "400": {
+ "description": "Unexpected error",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/api/annotations/trace/{id}": {
+ "get": {
+ "description": "Returns all annotations for single trace",
+ "parameters": [
+ {
+ "name": "id",
+ "in": "path",
+ "description": "ID of trace to fetch",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Annotation response",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/Annotation"
+ }
+ }
+ }
+ }
+ },
+ "400": {
+ "description": "Unexpected error",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ }
+ }
+ }
+ }
+ }
+ },
+ "post": {
+ "description": "Create an annotation for a single trace",
+ "parameters": [
+ {
+ "name": "id",
+ "in": "path",
+ "description": "ID of the trace to annotate",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "requestBody": {
+ "description": "Annotation data",
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": {
+ "comment": {
+ "type": "string"
+ },
+ "isThumbsUp": {
+ "type": "boolean"
+ },
+ "email": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "responses": {
+ "200": {
+ "description": "Annotation created",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Annotation"
+ }
+ }
+ }
+ },
+ "400": {
+ "description": "Invalid input",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/api/annotations/{id}": {
+ "get": {
+ "description": "Returns a single annotation based on the ID supplied",
+ "parameters": [
+ {
+ "name": "id",
+ "in": "path",
+ "description": "ID of annotation to fetch",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Annotation response",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Annotation"
+ }
+ }
+ }
+ },
+ "400": {
+ "description": "Unexpected error",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ }
+ }
+ }
+ }
+ }
+ },
+ "delete": {
+ "description": "Deletes a single annotation based on the ID supplied",
+ "parameters": [
+ {
+ "name": "id",
+ "in": "path",
+ "description": "ID of annotation to delete",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Annotation response",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": {
+ "status": {
+ "type": "string"
+ },
+ "message": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "400": {
+ "description": "Unexpected error",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ }
+ }
+ }
+ }
+ }
+ },
+ "patch": {
+ "description": "Updates a single annotation based on the ID supplied",
+ "parameters": [
+ {
+ "name": "id",
+ "in": "path",
+ "description": "ID of annotation to delete",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": {
+ "comment": {
+ "type": "string"
+ },
+ "isThumbsUp": {
+ "type": "boolean"
+ },
+ "email": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "responses": {
+ "200": {
+ "description": "Annotation response",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": {
+ "status": {
+ "type": "string"
+ },
+ "message": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "400": {
+ "description": "Unexpected error",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/api/trace/{id}": {
+ "get": {
+ "description": "Returns single trace details based on the ID supplied",
+ "parameters": [
+ {
+ "name": "id",
+ "in": "path",
+ "description": "ID of trace to share",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Trace details with spans and evaluations",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": {
+ "trace_id": {
+ "type": "string",
+ "example": "trace_BKZL_X0TKSD4oa1aBJTc_"
+ },
+ "project_id": {
+ "type": "string",
+ "example": "KAXYxPR8MUgTcP8CF193y"
+ },
+ "metadata": {
+ "type": "object",
+ "properties": {
+ "sdk_version": {
+ "type": "string",
+ "example": "0.1.11"
+ },
+ "sdk_language": {
+ "type": "string",
+ "example": "python"
+ }
+ }
+ },
+ "timestamps": {
+ "type": "object",
+ "properties": {
+ "started_at": {
+ "type": "integer",
+ "example": 1721382486868
+ },
+ "inserted_at": {
+ "type": "integer",
+ "example": 1721382492894
+ },
+ "updated_at": {
+ "type": "integer",
+ "example": 1721382492894
+ }
+ }
+ },
+ "input": {
+ "type": "object",
+ "properties": {
+ "value": {
+ "type": "string",
+ "example": "hi"
+ }
+ }
+ },
+ "output": {
+ "type": "object",
+ "properties": {
+ "value": {
+ "type": "string",
+ "example": "Hey there! ๐๐"
+ }
+ }
+ },
+ "metrics": {
+ "type": "object",
+ "properties": {
+ "first_token_ms": {
+ "type": "integer",
+ "example": 1449
+ },
+ "total_time_ms": {
+ "type": "integer",
+ "example": 1543
+ },
+ "prompt_tokens": {
+ "type": "integer",
+ "example": 20
+ },
+ "completion_tokens": {
+ "type": "integer",
+ "example": 7
+ },
+ "tokens_estimated": {
+ "type": "boolean",
+ "example": true
+ }
+ }
+ },
+ "error": {
+ "type": "object",
+ "nullable": true,
+ "properties": {
+ "stacktrace": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "message": {
+ "type": "string"
+ },
+ "has_error": {
+ "type": "boolean"
+ }
+ },
+ "example": null
+ },
+ "indexing_md5s": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "example": ["cccd21e0b70c706034dfd9f7772816a3"]
+ },
+ "spans": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "trace_id": {
+ "type": "string",
+ "example": "trace_BKZL_X0TKSD4oa1aBJTc_"
+ },
+ "span_id": {
+ "type": "string",
+ "example": "span_h1xUkcUJilhudDrLeQbR_"
+ },
+ "timestamps": {
+ "type": "object",
+ "properties": {
+ "finished_at": {
+ "type": "integer",
+ "example": 1721382488392
+ },
+ "updated_at": {
+ "type": "integer",
+ "example": 1721382492027
+ },
+ "started_at": {
+ "type": "integer",
+ "example": 1721382486895
+ },
+ "first_token_at": {
+ "type": "integer",
+ "example": 1721382488317
+ },
+ "inserted_at": {
+ "type": "integer",
+ "example": 1721382492027
+ }
+ }
+ },
+ "type": {
+ "type": "string",
+ "example": "llm"
+ },
+ "error": {
+ "type": "object",
+ "nullable": true,
+ "properties": {
+ "stacktrace": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "message": {
+ "type": "string"
+ },
+ "has_error": {
+ "type": "boolean"
+ }
+ },
+ "example": null
+ },
+ "params": {
+ "type": "object",
+ "properties": {
+ "stream": {
+ "type": "boolean",
+ "example": true
+ },
+ "temperature": {
+ "type": "number",
+ "example": 1
+ }
+ }
+ },
+ "project_id": {
+ "type": "string",
+ "example": "KAXYxPR8MUgTcP8CF193y"
+ },
+ "parent_id": {
+ "type": "string",
+ "nullable": true,
+ "example": "span_ijZNjUMTz3ys0Z0YKwF_T"
+ },
+ "name": {
+ "type": "string",
+ "nullable": true,
+ "example": null
+ },
+ "model": {
+ "type": "string",
+ "example": "openai/gpt-4o"
+ },
+ "metrics": {
+ "type": "object",
+ "properties": {
+ "tokens_estimated": {
+ "type": "boolean",
+ "example": true
+ },
+ "completion_tokens": {
+ "type": "integer",
+ "example": 7
+ },
+ "prompt_tokens": {
+ "type": "integer",
+ "example": 20
+ }
+ }
+ },
+ "input": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string",
+ "example": "chat_messages"
+ },
+ "value": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "role": {
+ "type": "string",
+ "example": "system"
+ },
+ "content": {
+ "type": "string",
+ "example": "You are a helpful assistant that only reply in short tweet-like responses, using lots of emojis."
+ }
+ }
+ },
+ "example": [
+ {
+ "role": "system",
+ "content": "You are a helpful assistant that only reply in short tweet-like responses, using lots of emojis."
+ },
+ {
+ "role": "user",
+ "content": "hi"
+ }
+ ]
+ }
+ }
+ },
+ "output": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string",
+ "example": "chat_messages"
+ },
+ "value": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "role": {
+ "type": "string",
+ "example": "assistant"
+ },
+ "content": {
+ "type": "string",
+ "example": "Hey there! ๐๐"
+ }
+ }
+ },
+ "example": [
+ {
+ "role": "assistant",
+ "content": "Hey there! ๐๐"
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ },
+ "evaluations": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "evaluation_id": {
+ "type": "string",
+ "example": "check_VCagriZHNWICSOM09dXjM"
+ },
+ "name": {
+ "type": "string",
+ "example": "Ragas Answer Relevancy"
+ },
+ "type": {
+ "type": "string",
+ "example": "ragas/answer_relevancy"
+ },
+ "trace_id": {
+ "type": "string",
+ "example": "trace_BKZL_X0TKSD4oa1aBJTc_"
+ },
+ "project_id": {
+ "type": "string",
+ "example": "KAXYxPR8MUgTcP8CF193y"
+ },
+ "status": {
+ "type": "string",
+ "example": "error"
+ },
+ "timestamps": {
+ "type": "object",
+ "properties": {
+ "updated_at": {
+ "type": "integer",
+ "example": 1721383657788
+ },
+ "inserted_at": {
+ "type": "integer",
+ "example": 1721382493358
+ }
+ }
+ },
+ "error": {
+ "type": "object",
+ "properties": {
+ "stacktrace": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "example": ["TypeError: fetch failed"]
+ },
+ "message": {
+ "type": "string",
+ "example": "fetch failed"
+ },
+ "has_error": {
+ "type": "boolean",
+ "example": true
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "400": {
+ "description": "Unexpected error",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/api/trace/search": {
+ "post": {
+ "summary": "Search traces",
+ "description": "Search for traces based on given criteria",
+ "tags": ["Traces"],
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/SearchRequest"
+ }
+ }
+ }
+ },
+ "responses": {
+ "200": {
+ "description": "Successful response",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/SearchResponse"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/api/trace/{id}/share": {
+ "post": {
+ "description": "Returns a public path for a trace",
+ "parameters": [
+ {
+ "name": "id",
+ "in": "path",
+ "description": "ID of trace to share",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Public path created",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": {
+ "path": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "400": {
+ "description": "Unexpected error",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/api/trace/{id}/unshare": {
+ "post": {
+ "description": "Deletes a public path for a trace",
+ "parameters": [
+ {
+ "name": "id",
+ "in": "path",
+ "description": "ID of trace to unshare",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Public path deleted",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": {
+ "message": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "400": {
+ "description": "Unexpected error",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/api/dataset/{slug}/entries": {
+ "post": {
+ "responses": {},
+ "operationId": "postApiDatasetBySlugEntries",
+ "parameters": [
+ {
+ "schema": {
+ "type": "string"
+ },
+ "in": "path",
+ "name": "slug",
+ "required": true
+ }
+ ],
+ "description": "Add entries to a dataset",
+ "requestBody": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/DatasetPostEntries"
+ }
+ }
+ }
+ }
+ }
+ },
+ "/api/prompts": {
+ "get": {
+ "responses": {},
+ "operationId": "getApiPrompts",
+ "parameters": [],
+ "description": "Get all prompts for a project"
+ },
+ "post": {
+ "responses": {},
+ "operationId": "postApiPrompts",
+ "parameters": [],
+ "description": "Create a new prompt",
+ "requestBody": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string",
+ "minLength": 1
+ }
+ },
+ "required": ["name"]
+ }
+ }
+ }
+ }
+ }
+ },
+ "/api/prompts/{id}": {
+ "get": {
+ "responses": {},
+ "operationId": "getApiPromptsById",
+ "parameters": [
+ {
+ "schema": {
+ "type": "string"
+ },
+ "in": "path",
+ "name": "id",
+ "required": true
+ }
+ ],
+ "description": "Get a specific prompt"
+ },
+ "put": {
+ "responses": {},
+ "operationId": "putApiPromptsById",
+ "parameters": [
+ {
+ "schema": {
+ "type": "string"
+ },
+ "in": "path",
+ "name": "id",
+ "required": true
+ }
+ ],
+ "description": "Update a prompt",
+ "requestBody": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string",
+ "minLength": 1
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "delete": {
+ "responses": {},
+ "operationId": "deleteApiPromptsById",
+ "parameters": [
+ {
+ "schema": {
+ "type": "string"
+ },
+ "in": "path",
+ "name": "id",
+ "required": true
+ }
+ ],
+ "description": "Delete a prompt"
+ }
+ },
+ "/api/prompts/{id}/versions": {
+ "get": {
+ "responses": {},
+ "operationId": "getApiPromptsByIdVersions",
+ "parameters": [
+ {
+ "schema": {
+ "type": "string"
+ },
+ "in": "path",
+ "name": "id",
+ "required": true
+ }
+ ],
+ "description": "Get all versions for a prompt"
+ },
+ "post": {
+ "responses": {},
+ "operationId": "postApiPromptsByIdVersions",
+ "parameters": [
+ {
+ "schema": {
+ "type": "string"
+ },
+ "in": "path",
+ "name": "id",
+ "required": true
+ }
+ ],
+ "description": "Create a new version for a prompt",
+ "requestBody": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": {
+ "authorId": {
+ "type": ["string", "null"]
+ },
+ "projectId": {
+ "type": "string",
+ "minLength": 1
+ },
+ "configId": {
+ "type": "string",
+ "minLength": 1
+ },
+ "schemaVersion": {
+ "type": "string",
+ "const": "1.0"
+ },
+ "commitMessage": {
+ "type": "string"
+ },
+ "configData": {
+ "type": "object",
+ "properties": {
+ "version": {
+ "type": "string",
+ "const": "1.0"
+ },
+ "prompt": {
+ "type": "string",
+ "minLength": 1
+ },
+ "model": {
+ "type": "string",
+ "minLength": 1
+ },
+ "inputs": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "identifier": {
+ "type": "string",
+ "minLength": 1
+ },
+ "type": {
+ "type": "string",
+ "minLength": 1
+ }
+ },
+ "required": ["identifier", "type"]
+ },
+ "minItems": 1
+ },
+ "outputs": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "identifier": {
+ "type": "string",
+ "minLength": 1
+ },
+ "type": {
+ "type": "string",
+ "minLength": 1
+ }
+ },
+ "required": ["identifier", "type"]
+ },
+ "minItems": 1
+ },
+ "demonstrations": {
+ "type": "object",
+ "properties": {
+ "columns": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "type": {
+ "type": "string",
+ "minLength": 1
+ }
+ },
+ "required": ["name", "type"]
+ }
+ },
+ "rows": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": {}
+ },
+ "default": []
+ }
+ },
+ "required": ["columns"]
+ }
+ },
+ "required": [
+ "version",
+ "prompt",
+ "model",
+ "inputs",
+ "outputs",
+ "demonstrations"
+ ]
+ }
+ },
+ "required": [
+ "authorId",
+ "projectId",
+ "configId",
+ "schemaVersion",
+ "commitMessage",
+ "configData"
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "components": {
+ "schemas": {
+ "Annotation": {
+ "required": ["name"],
+ "type": "object",
+ "properties": {
+ "id": {
+ "description": "The ID of the annotation",
+ "type": "string"
+ },
+ "projectId": {
+ "description": "The ID of the project",
+ "type": "string"
+ },
+ "traceId": {
+ "description": "The ID of the trace",
+ "type": "string"
+ },
+ "comment": {
+ "description": "The comment of the annotation",
+ "type": "string"
+ },
+ "isThumbsUp": {
+ "description": "The thumbs up status of the annotation",
+ "type": "boolean"
+ },
+ "userId": {
+ "description": "The ID of the user",
+ "type": "string"
+ },
+ "createdAt": {
+ "description": "The created at of the annotation",
+ "type": "string"
+ },
+ "updatedAt": {
+ "description": "The updated at of the annotation",
+ "type": "string"
+ },
+ "email": {
+ "description": "The email of the user",
+ "type": "string"
+ }
+ }
+ },
+ "Error": {
+ "required": ["error", "message"],
+ "type": "object",
+ "properties": {
+ "error": {
+ "type": "integer",
+ "format": "int32"
+ },
+ "message": {
+ "type": "string"
+ }
+ }
+ },
+ "SearchRequest": {
+ "type": "object",
+ "properties": {
+ "query": {
+ "type": "string"
+ },
+ "startDate": {
+ "type": "string",
+ "format": "date-time"
+ },
+ "endDate": {
+ "type": "string",
+ "format": "date-time"
+ },
+ "pageSize": {
+ "type": "integer",
+ "example": 1000
+ },
+ "scrollId": {
+ "type": "string",
+ "example": "123"
+ },
+ "filters": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ },
+ "SearchResponse": {
+ "type": "object",
+ "properties": {
+ "traces": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/Trace"
+ }
+ },
+ "pagination": {
+ "$ref": "#/components/schemas/Pagination"
+ }
+ }
+ },
+ "Trace": {
+ "type": "object",
+ "properties": {
+ "trace_id": {
+ "type": "string"
+ },
+ "project_id": {
+ "type": "string"
+ },
+ "timestamps": {
+ "$ref": "#/components/schemas/Timestamps"
+ },
+ "input": {
+ "$ref": "#/components/schemas/Input"
+ },
+ "output": {
+ "$ref": "#/components/schemas/Output"
+ },
+ "metadata": {
+ "$ref": "#/components/schemas/Metadata"
+ },
+ "metrics": {
+ "$ref": "#/components/schemas/Metrics"
+ },
+ "indexing_md5s": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "error": {
+ "type": "string",
+ "nullable": true
+ },
+ "evaluations": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/Evaluation"
+ }
+ },
+ "contexts": {
+ "type": "array",
+ "items": {}
+ }
+ }
+ },
+ "Timestamps": {
+ "type": "object",
+ "properties": {
+ "inserted_at": {
+ "type": "integer"
+ },
+ "started_at": {
+ "type": "integer"
+ },
+ "updated_at": {
+ "type": "integer"
+ }
+ }
+ },
+ "Input": {
+ "type": "object",
+ "properties": {
+ "value": {
+ "type": "string"
+ },
+ "satisfaction_score": {
+ "type": "number"
+ }
+ }
+ },
+ "Output": {
+ "type": "object",
+ "properties": {
+ "value": {
+ "type": "string"
+ }
+ }
+ },
+ "Metadata": {
+ "type": "object",
+ "properties": {
+ "sdk_language": {
+ "type": "string"
+ },
+ "sdk_version": {
+ "type": "string"
+ }
+ }
+ },
+ "Metrics": {
+ "type": "object",
+ "properties": {
+ "tokens_estimated": {
+ "type": "boolean"
+ },
+ "completion_tokens": {
+ "type": "integer"
+ },
+ "prompt_tokens": {
+ "type": "integer"
+ },
+ "total_cost": {
+ "type": "number"
+ },
+ "total_time_ms": {
+ "type": "integer"
+ },
+ "first_token_ms": {
+ "type": "integer",
+ "nullable": true
+ }
+ }
+ },
+ "Evaluation": {
+ "type": "object",
+ "properties": {
+ "evaluation_id": {
+ "type": "string"
+ },
+ "score": {
+ "type": "number"
+ },
+ "timestamps": {
+ "$ref": "#/components/schemas/EvaluationTimestamps"
+ },
+ "evaluator_id": {
+ "type": "string"
+ },
+ "name": {
+ "type": "string"
+ },
+ "details": {
+ "type": "string"
+ },
+ "passed": {
+ "type": "boolean"
+ },
+ "label": {
+ "type": "string",
+ "nullable": true
+ },
+ "type": {
+ "type": "string"
+ },
+ "status": {
+ "type": "string"
+ }
+ }
+ },
+ "EvaluationTimestamps": {
+ "type": "object",
+ "properties": {
+ "finished_at": {
+ "type": "integer"
+ },
+ "updated_at": {
+ "type": "integer"
+ }
+ }
+ },
+ "Pagination": {
+ "type": "object",
+ "properties": {
+ "scrollId": {
+ "type": "string",
+ "example": "123"
+ },
+ "totalHits": {
+ "type": "integer",
+ "example": 1254
+ }
+ }
+ },
+ "DatasetPostEntries": {
+ "type": "object",
+ "properties": {
+ "entries": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": {}
+ },
+ "example": [
+ {
+ "input": "hi",
+ "output": "Hello, how can I help you today?"
+ }
+ ]
+ }
+ },
+ "required": ["entries"]
+ }
+ },
+ "securitySchemes": {
+ "api_key": {
+ "type": "apiKey",
+ "in": "header",
+ "name": "X-Auth-Token"
+ }
+ }
+ }
+}
diff --git a/api-reference/traces/create-public-trace-path.mdx b/api-reference/traces/create-public-trace-path.mdx
new file mode 100644
index 000000000..9e31d113f
--- /dev/null
+++ b/api-reference/traces/create-public-trace-path.mdx
@@ -0,0 +1,4 @@
+---
+title: 'Create public path for single trace'
+openapi: 'POST /api/trace/{id}/share'
+---
diff --git a/api-reference/traces/delete-public-trace-path.mdx b/api-reference/traces/delete-public-trace-path.mdx
new file mode 100644
index 000000000..20ae59430
--- /dev/null
+++ b/api-reference/traces/delete-public-trace-path.mdx
@@ -0,0 +1,4 @@
+---
+title: 'Delete an existing public path for a trace'
+openapi: 'POST /api/trace/{id}/unshare'
+---
diff --git a/api-reference/traces/get-trace-details.mdx b/api-reference/traces/get-trace-details.mdx
new file mode 100644
index 000000000..0a1dddd95
--- /dev/null
+++ b/api-reference/traces/get-trace-details.mdx
@@ -0,0 +1,4 @@
+---
+title: 'Get trace details'
+openapi: 'GET /api/trace/{id}'
+---
diff --git a/api-reference/traces/overview.mdx b/api-reference/traces/overview.mdx
new file mode 100644
index 000000000..ca0d2be71
--- /dev/null
+++ b/api-reference/traces/overview.mdx
@@ -0,0 +1,18 @@
+---
+title: 'Overview'
+description: 'A Trace is a collection of runs that are related to a single operation'
+---
+
+## Intro
+
+With the Traces API, you are able to create a public path for a trace. This is useful if you want to share a trace with a colleague.
+
+## Authentication
+
+To make a call to the Traces API, you will need to pass through your LangWatch API key in the header as `X-Auth-Token`. Your API key can be found on the setup page under settings.
+
+
+#### Allowed Methods
+
+- `GET /api/trace/:id` - Get trace details
+- `POST /api/trace/:id/share` - Create a public path for a trace
diff --git a/api-reference/traces/search-traces.mdx b/api-reference/traces/search-traces.mdx
new file mode 100644
index 000000000..4217d8bbf
--- /dev/null
+++ b/api-reference/traces/search-traces.mdx
@@ -0,0 +1,4 @@
+---
+title: 'Search traces'
+openapi: 'POST /api/trace/search'
+---
diff --git a/concepts.mdx b/concepts.mdx
new file mode 100644
index 000000000..473cdb045
--- /dev/null
+++ b/concepts.mdx
@@ -0,0 +1,50 @@
+---
+title: Concepts
+---
+
+Understanding LangWatch concepts can be made easier with two practical examples: an AI travel assistant and a tool for generating blog posts. Let's dive into how each core concept of LangWatch applies to these examples.
+
+Imagine you've created an AI travel assistant that helps users plan their trips by conversing with them to suggest destinations, find the best prices for flights, and assist with bookings. On the other hand, you also have a platform that assists users in generating, and refining blog posts, including SEO optimization.
+
+### Threads
+
+Field: `thread_id`
+
+A **thread** in the context of the AI travel assistant represents a complete conversation, that is, the group of all traces. It's the entire chat that groups all back-and-forth messages as the user inquires about different aspects of their travel plan. For the blog post tool, a thread could be for example the creation process of a new blog post, encapsulating all interactions that contribute to its completionโfrom headline generation to the final SEO adjustments.
+
+### Traces
+
+Field: `trace_id`
+
+A **trace** in the travel assistant's example is each distinct message, for example when a user asks for the best prices for a destination, or asks if pets are allowed in the hotel.
+
+In the blog post tool case, a trace could be for example each time a new generation of a catchy headline option happens, or the generation of a draft for the body, or the SEO keywords generation.
+
+It does not matter how many steps are inside, each trace is a full end-to-end generation handled by the AI.
+
+The `trace_id` is by default randomly generated if you don't provide one, however, to keep control of your traces and connect them to events like [Thumbs Up/Down](./user-events/thumbs-up-down), we recommend generating a random id on your side, using, for example the [nanoid](https://pypi.org/project/nanoid/) library.
+
+### Spans
+
+Field: `span_id`
+
+Within each trace, **spans** represent the individual steps taken to achieve the outcome. In the travel bot scenario, a span could be a call to the LLM to suggest potential destinations, another span for querying the airline price API, and a final span for formatting the response to present to the user. For the blog post tool, one span might be the initial text generation, followed by a subsequent span for LLM to self-critiquing the content, and another span for the third LLM call refining the text based on the critique.
+
+### User ID
+
+Field: `user_id`
+
+The **user id** identifies the ID of the final user of the product. In the context of both the AI travel assistant and the tool for generating blog posts, it's the ID that identifies the person using the app, usually their user account ID, this allows LangWatch to track how end users are using the product.
+
+### Customer ID
+
+Field: `customer_id`
+
+The **customer id** is used when you provide a platform for your customers to build LLM apps for their end users. For example, it would be if your are building a platform that allow _others_ to build AI assistants for _their_ users. Having the **customer id** allows LangWatch to group all metrics and messages per customer, which allows you to access LangWatch data through our APIs to build a custom analytics dashboard for your customers, so they can see how their own LLM assistants are behaving.
+
+### Labels
+
+Field: `labels`
+
+You can use **labels** to organize and compare the traces sent to LangWatch for any comparison you want to do. You can for example apply different labels for different actions, for example a label `blogpost_title` for generating the blog post title and another `blogpost_keywords`, for generating keywords. You can use it for versioning as well, for example label the first implementation
+version as `v1.0.0`, then do a prompt engineering to improve the AI travel planner itenerary builder, and label it as `v1.0.1`. This way you can easily focus on each different functionality or compare versions on LangWatch dashboard.
diff --git a/development.mdx b/development.mdx
deleted file mode 100644
index 878300893..000000000
--- a/development.mdx
+++ /dev/null
@@ -1,98 +0,0 @@
----
-title: 'Development'
-description: 'Learn how to preview changes locally'
----
-
-
- **Prerequisite** You should have installed Node.js (version 18.10.0 or
- higher).
-
-
-Step 1. Install Mintlify on your OS:
-
-
-
-```bash npm
-npm i -g mintlify
-```
-
-```bash yarn
-yarn global add mintlify
-```
-
-
-
-Step 2. Go to the docs are located (where you can find `mint.json`) and run the following command:
-
-```bash
-mintlify dev
-```
-
-The documentation website is now available at `http://localhost:3000`.
-
-### Custom Ports
-
-Mintlify uses port 3000 by default. You can use the `--port` flag to customize the port Mintlify runs on. For example, use this command to run in port 3333:
-
-```bash
-mintlify dev --port 3333
-```
-
-You will see an error like this if you try to run Mintlify in a port that's already taken:
-
-```md
-Error: listen EADDRINUSE: address already in use :::3000
-```
-
-## Mintlify Versions
-
-Each CLI is linked to a specific version of Mintlify. Please update the CLI if your local website looks different than production.
-
-
-
-```bash npm
-npm i -g mintlify@latest
-```
-
-```bash yarn
-yarn global upgrade mintlify
-```
-
-
-
-## Deployment
-
-
- Unlimited editors available under the [Startup
- Plan](https://mintlify.com/pricing)
-
-
-You should see the following if the deploy successfully went through:
-
-
-
-
-
-## Troubleshooting
-
-Here's how to solve some common problems when working with the CLI.
-
-
-
- Update to Node v18. Run `mintlify install` and try again.
-
-
-Go to the `C:/Users/Username/.mintlify/` directory and remove the `mint`
-folder. Then Open the Git Bash in this location and run `git clone
-https://github.com/mintlify/mint.git`.
-
-Repeat step 3.
-
-
-
- Try navigating to the root of your device and delete the ~/.mintlify folder.
- Then run `mintlify dev` again.
-
-
-
-Curious about what changed in a CLI version? [Check out the CLI changelog.](/changelog/command-line)
diff --git a/dspy-visualization/custom-optimizer.mdx b/dspy-visualization/custom-optimizer.mdx
new file mode 100644
index 000000000..1966a8fa1
--- /dev/null
+++ b/dspy-visualization/custom-optimizer.mdx
@@ -0,0 +1,51 @@
+---
+title: Tracking Custom DSPy Optimizer
+sidebarTitle: Custom Optimizer Tracking
+---
+
+If you are building a custom DSPy optimizer, then LangWatch won't support tracking it out of the box, but adding track to any custom optimizer is also very simple.
+
+## 1. Initialize LangWatch DSPy with optimizer=None
+
+Before the compilation step, explicitly provide `None` on the `optimizer` parameter to be able to track the steps manually:
+
+```python
+langwatch.dspy.init(experiment="dspy-custom-optimizer-example", optimizer=None)
+
+compiled_rag = my_awesome_optimizer.compile(RAG(), trainset=trainset)
+```
+
+## 2. Track the metric function
+
+Either before instantiating your optimizer, or inside the compilation step, don't forget to wrap the metric function with `langwatch.dspy.track_metric` so that it's tracked:
+
+```python
+metric = langwatch.dspy.track_metric(metric)
+```
+
+## 3. Track each step
+
+Now at each step your optimizer progresses, call `langwatch.dspy.log_step` to capture the score at the current step index, optimizer info and predictors being used on this step evaluation:
+
+```python
+langwatch.dspy.log_step(
+ optimizer=DSPyOptimizer(
+ name="MyAwesomeOptimizer",
+ parameters={
+ "hyperparam": 1,
+ },
+ ),
+ index="1", # step index
+ score=0.5,
+ label="score",
+ predictors=candidate_program.predictors(),
+)
+```
+
+The LLM calls and examples being evaluated with be tracked automatically and logged in together with calling `log_step`.
+
+## Wrapping up
+
+That's it! You should see the steps of the optimizer in the LangWatch dashboard now.
+
+For any questions or issues, feel free to contact our support, join our channel on [Discord](https://discord.com/invite/kT4PhDS2gH) or [open an issue](https://github.com/langwatch/langwatch/issues) on our GitHub.
diff --git a/dspy-visualization/quickstart.mdx b/dspy-visualization/quickstart.mdx
new file mode 100644
index 000000000..a314ea3e4
--- /dev/null
+++ b/dspy-visualization/quickstart.mdx
@@ -0,0 +1,65 @@
+---
+title: DSPy Visualization Quickstart
+sidebarTitle: Quickstart
+---
+
+[](https://colab.research.google.com/github/langwatch/langwatch/blob/main/python-sdk/examples/dspy_visualization.ipynb)
+
+LangWatch DSPy Visualization allows you to start tracking your DSPy experiments in real-time and easily follow the progress, track costs and debug each step.
+
+## 1. Install the Python library
+
+
+
+ ```bash
+ !pip install langwatch
+ ```
+
+
+ ```bash
+ pip install langwatch
+ ```
+
+
+
+## 2. Login to LangWatch
+
+Import and authenticate the LangWatch SDK:
+
+```python
+import langwatch
+
+langwatch.login()
+```
+
+Be sure to login or create an account on the link that will be displayed, then provide your API key when prompted.
+
+## 3. Start tracking
+
+Before your DSPy program compilation starts, initialize langwatch with your experiment name and the optimizer to be tracked:
+
+```python
+# Initialize langwatch for this run, to track the optimizer compilation
+langwatch.dspy.init(experiment="my-awesome-experiment", optimizer=optimizer)
+
+compiled_rag = optimizer.compile(RAG(), trainset=trainset)
+```
+
+## Follow your experiment
+
+Open the link provided when the compilation starts or go to your [LangWatch dashboard](https://app.langwatch.com) to follow the progress of your experiments:
+
+
+
+
+
+## Wrapping up
+
+With your experiments tracked on LangWatch, now it's time to explore how is the training going, take a look at the examples, the llm calls,
+the different steps and so on, so you can understand and hypothesize where you could improve your DSPy program, and keep iterating!
+
+
+When you are ready to deploy your DSPy program, you can monitor the inference traces on LangWatch dashboard as well. Check out the [Python Integration Guide](/integration/python/guide) for more details.
+
+
+For any questions or issues, feel free to contact our support, join our channel on [Discord](https://discord.com/invite/kT4PhDS2gH) or [open an issue](https://github.com/langwatch/langwatch/issues) on our GitHub.
diff --git a/dspy-visualization/rag-visualization.mdx b/dspy-visualization/rag-visualization.mdx
new file mode 100644
index 000000000..ec9f753f4
--- /dev/null
+++ b/dspy-visualization/rag-visualization.mdx
@@ -0,0 +1,105 @@
+---
+title: "RAG Visualization"
+---
+
+[](https://colab.research.google.com/github/langwatch/langevals/blob/main/notebooks/tutorials/dspy_rag.ipynb)
+
+In this tutorial we will explain how LangWatch can help observing optimization of RAG application with [DSPy](https://dspy-docs.vercel.app).
+
+## DSPy RAG Module
+As an example of RAG application we will use the sample app that is provided in the official documentation of DSPy library,
+you can read more by following this link - [RAG tutorial](https://dspy-docs.vercel.app/docs/tutorials/rag).
+
+Firstly, lets access the dataset of wiki abstracts that will be used for example RAG optimization.
+
+```python
+import dspy
+
+turbo = dspy.OpenAI(model='gpt-3.5-turbo')
+colbertv2_wiki17_abstracts = dspy.ColBERTv2(url='http://20.102.90.50:2017/wiki17_abstracts')
+
+dspy.settings.configure(lm=turbo, rm=colbertv2_wiki17_abstracts)
+
+from dspy.datasets import HotPotQA
+
+# Load the dataset.
+dataset = HotPotQA(train_seed=1, train_size=20, eval_seed=2023, dev_size=50, test_size=0)
+
+# Tell DSPy that the 'question' field is the input. Any other fields are labels and/or metadata.
+trainset = [x.with_inputs('question') for x in dataset.train]
+devset = [x.with_inputs('question') for x in dataset.dev]
+
+len(trainset), len(devset)
+```
+
+Next step - to define the RAG module itself.
+You can explain the task and what the expected outputs mean in this context that an LLM can optimize these commands later.
+
+```python
+class GenerateAnswer(dspy.Signature):
+ """Answer questions with short factoid answers."""
+
+ context = dspy.InputField(desc="may contain relevant facts")
+ question = dspy.InputField()
+ answer = dspy.OutputField(desc="often between 1 and 5 words")
+
+
+class RAG(dspy.Module):
+ def __init__(self, num_passages=3):
+ super().__init__()
+
+ self.retrieve = dspy.Retrieve(k=num_passages)
+ self.generate_answer = dspy.ChainOfThought(GenerateAnswer)
+
+ def forward(self, question):
+ context = self.retrieve(question).passages
+ prediction = self.generate_answer(context=context, question=question)
+ return dspy.Prediction(context=context, answer=prediction.answer)
+```
+Finally, you can connect to LangWatch. After running this code snippet - you will get a link that will give you access to
+an `api_key` in the browser. Paste the API key into your code editor popup and press enter - **now you are connected to LangWatch**.
+
+```python
+import langwatch
+
+langwatch.endpoint = "https://app.langwatch.ai"
+langwatch.login()
+```
+
+Last step is to actually run the prompt optitmizer. In this example `BootstrapFewShot` is used and it will
+bootstrap our prompt with the best demos from our dataset.
+
+```python
+from dspy.teleprompt import BootstrapFewShot
+from dspy import evaluate
+from dotenv import load_dotenv
+load_dotenv()
+
+# Validation logic: check that the predicted answer is correct.
+# Also check that the retrieved context does actually contain that answer.
+def validate_context_and_answer(example, pred, trace=None):
+ answer_EM = evaluate.answer_exact_match(example, pred)
+ answer_PM = evaluate.answer_passage_match(example, pred)
+ return answer_EM and answer_PM
+
+# Set up a basic teleprompter, which will compile our RAG program.
+teleprompter = BootstrapFewShot(metric=validate_context_and_answer)
+
+langwatch.dspy.init(experiment="rag-dspy-tutorial", optimizer=teleprompter)
+
+# Compile!
+compiled_rag = teleprompter.compile(RAG(), trainset=trainset)
+```
+
+The result of optimization can be found on your LangWatch dashboard. On the graph you can see how many demos were boostrapped during the first optimization step.
+
+
+
+Additionally, you can see each LLM call that has been done during the optimization with the corresponding costs and token counts.
+
+
+
+
+ You can access and run the code yourself in Jupyter Notebook
+
+
diff --git a/essentials/images.mdx b/essentials/images.mdx
deleted file mode 100644
index 60ad42d38..000000000
--- a/essentials/images.mdx
+++ /dev/null
@@ -1,59 +0,0 @@
----
-title: 'Images and Embeds'
-description: 'Add image, video, and other HTML elements'
-icon: 'image'
----
-
-
-
-## Image
-
-### Using Markdown
-
-The [markdown syntax](https://www.markdownguide.org/basic-syntax/#images) lets you add images using the following code
-
-```md
-
-```
-
-Note that the image file size must be less than 5MB. Otherwise, we recommend hosting on a service like [Cloudinary](https://cloudinary.com/) or [S3](https://aws.amazon.com/s3/). You can then use that URL and embed.
-
-### Using Embeds
-
-To get more customizability with images, you can also use [embeds](/writing-content/embed) to add images
-
-```html
-
-```
-
-## Embeds and HTML elements
-
-
-
-
-
-
-
-Mintlify supports [HTML tags in Markdown](https://www.markdownguide.org/basic-syntax/#html). This is helpful if you prefer HTML tags to Markdown syntax, and lets you create documentation with infinite flexibility.
-
-
-
-### iFrames
-
-Loads another HTML page within the document. Most commonly used for embedding videos.
-
-```html
-
-```
diff --git a/essentials/settings.mdx b/essentials/settings.mdx
deleted file mode 100644
index d9dd2d7e1..000000000
--- a/essentials/settings.mdx
+++ /dev/null
@@ -1,318 +0,0 @@
----
-title: 'Global Settings'
-description: 'Mintlify gives you complete control over the look and feel of your documentation using the mint.json file'
-icon: 'gear'
----
-
-Every Mintlify site needs a `mint.json` file with the core configuration settings. Learn more about the [properties](#properties) below.
-
-## Properties
-
-
-Name of your project. Used for the global title.
-
-Example: `mintlify`
-
-
-
-
- An array of groups with all the pages within that group
-
-
- The name of the group.
-
- Example: `Settings`
-
-
-
- The relative paths to the markdown files that will serve as pages.
-
- Example: `["customization", "page"]`
-
-
-
-
-
-
-
- Path to logo image or object with path to "light" and "dark" mode logo images
-
-
- Path to the logo in light mode
-
-
- Path to the logo in dark mode
-
-
- Where clicking on the logo links you to
-
-
-
-
-
- Path to the favicon image
-
-
-
- Hex color codes for your global theme
-
-
- The primary color. Used for most often for highlighted content, section
- headers, accents, in light mode
-
-
- The primary color for dark mode. Used for most often for highlighted
- content, section headers, accents, in dark mode
-
-
- The primary color for important buttons
-
-
- The color of the background in both light and dark mode
-
-
- The hex color code of the background in light mode
-
-
- The hex color code of the background in dark mode
-
-
-
-
-
-
-
- Array of `name`s and `url`s of links you want to include in the topbar
-
-
- The name of the button.
-
- Example: `Contact us`
-
-
- The url once you click on the button. Example: `https://mintlify.com/contact`
-
-
-
-
-
-
-
-
- Link shows a button. GitHub shows the repo information at the url provided including the number of GitHub stars.
-
-
- If `link`: What the button links to.
-
- If `github`: Link to the repository to load GitHub information from.
-
-
- Text inside the button. Only required if `type` is a `link`.
-
-
-
-
-
-
- Array of version names. Only use this if you want to show different versions
- of docs with a dropdown in the navigation bar.
-
-
-
- An array of the anchors, includes the `icon`, `color`, and `url`.
-
-
- The [Font Awesome](https://fontawesome.com/search?s=brands%2Cduotone) icon used to feature the anchor.
-
- Example: `comments`
-
-
- The name of the anchor label.
-
- Example: `Community`
-
-
- The start of the URL that marks what pages go in the anchor. Generally, this is the name of the folder you put your pages in.
-
-
- The hex color of the anchor icon background. Can also be a gradient if you pass an object with the properties `from` and `to` that are each a hex color.
-
-
- Used if you want to hide an anchor until the correct docs version is selected.
-
-
- Pass `true` if you want to hide the anchor until you directly link someone to docs inside it.
-
-
- One of: "brands", "duotone", "light", "sharp-solid", "solid", or "thin"
-
-
-
-
-
-
- Override the default configurations for the top-most anchor.
-
-
- The name of the top-most anchor
-
-
- Font Awesome icon.
-
-
- One of: "brands", "duotone", "light", "sharp-solid", "solid", or "thin"
-
-
-
-
-
- An array of navigational tabs.
-
-
- The name of the tab label.
-
-
- The start of the URL that marks what pages go in the tab. Generally, this
- is the name of the folder you put your pages in.
-
-
-
-
-
- Configuration for API settings. Learn more about API pages at [API Components](/api-playground/demo).
-
-
- The base url for all API endpoints. If `baseUrl` is an array, it will enable for multiple base url
- options that the user can toggle.
-
-
-
-
-
- The authentication strategy used for all API endpoints.
-
-
- The name of the authentication parameter used in the API playground.
-
- If method is `basic`, the format should be `[usernameName]:[passwordName]`
-
-
- The default value that's designed to be a prefix for the authentication input field.
-
- E.g. If an `inputPrefix` of `AuthKey` would inherit the default input result of the authentication field as `AuthKey`.
-
-
-
-
-
- Configurations for the API playground
-
-
-
- Whether the playground is showing, hidden, or only displaying the endpoint with no added user interactivity `simple`
-
- Learn more at the [playground guides](/api-playground/demo)
-
-
-
-
-
- Enabling this flag ensures that key ordering in OpenAPI pages matches the key ordering defined in the OpenAPI file.
-
- This behavior will soon be enabled by default, at which point this field will be deprecated.
-
-
-
-
-
-
- A string or an array of strings of URL(s) or relative path(s) pointing to your
- OpenAPI file.
-
- Examples:
-
- ```json Absolute
- "openapi": "https://example.com/openapi.json"
- ```
- ```json Relative
- "openapi": "/openapi.json"
- ```
- ```json Multiple
- "openapi": ["https://example.com/openapi1.json", "/openapi2.json", "/openapi3.json"]
- ```
-
-
-
-
-
- An object of social media accounts where the key:property pair represents the social media platform and the account url.
-
- Example:
- ```json
- {
- "x": "https://x.com/mintlify",
- "website": "https://mintlify.com"
- }
- ```
-
-
- One of the following values `website`, `facebook`, `x`, `discord`, `slack`, `github`, `linkedin`, `instagram`, `hacker-news`
-
- Example: `x`
-
-
- The URL to the social platform.
-
- Example: `https://x.com/mintlify`
-
-
-
-
-
- Configurations to enable feedback buttons
-
-
-
- Enables a button to allow users to suggest edits via pull requests
-
-
- Enables a button to allow users to raise an issue about the documentation
-
-
-
-
-
- Customize the dark mode toggle.
-
-
- Set if you always want to show light or dark mode for new users. When not
- set, we default to the same mode as the user's operating system.
-
-
- Set to true to hide the dark/light mode toggle. You can combine `isHidden` with `default` to force your docs to only use light or dark mode. For example:
-
-
- ```json Only Dark Mode
- "modeToggle": {
- "default": "dark",
- "isHidden": true
- }
- ```
-
- ```json Only Light Mode
- "modeToggle": {
- "default": "light",
- "isHidden": true
- }
- ```
-
-
-
-
-
-
-
-
- A background image to be displayed behind every page. See example with
- [Infisical](https://infisical.com/docs) and [FRPC](https://frpc.io).
-
diff --git a/evaluations/custom-evaluator-integration.mdx b/evaluations/custom-evaluator-integration.mdx
new file mode 100644
index 000000000..7ef1b34c1
--- /dev/null
+++ b/evaluations/custom-evaluator-integration.mdx
@@ -0,0 +1,62 @@
+---
+title: Custom Evaluator Integration
+---
+
+If you have a custom evaluator built in-house which run on your own code, either during the LLM pipeline or after, you can still capture the evaluation results
+and connect it back to the trace to visualize it together with the other LangWatch evaluators.
+
+import PythonCustomEvaluation from "/snippets/python-custom-evaluation.mdx"
+import TypeScriptCustomEvaluation from "/snippets/typescript-custom-evaluation.mdx"
+
+
+
+
+You can capture the evaluation results of your custom evaluator on the current trace or span by using the `.add_evaluation` method:
+
+
+
+
+
+
+You can capture the evaluation results of your custom evaluator on the current trace or span by using the `.addEvaluation` method:
+
+
+
+
+
+
+## REST API Specification
+
+### Endpoint
+
+`POST /api/collector`
+
+### Headers
+
+- `X-Auth-Token`: Your LangWatch API key.
+
+### Request Body
+
+```javascript
+{
+ "trace_id": "id of the message the evaluation was run on",
+ "evaluations": [{
+ "evaluation_id": "evaluation-id-123", // optional unique id for identifying the evaluation, if not provided, a random id will be generated
+ "name": "custom evaluation", // required
+ "passed": true, // optional
+ "score": 0.5, // optional
+ "label": "category_detected", // optional
+ "details": "explanation of the evaluation results", // optional
+ "error": { // optional to capture error details in case evaluation had an error
+ "message": "error message",
+ "stacktrace": [],
+ },
+ "timestamps": { // optional
+ "created_at": "1723411698506", // unix timestamp in milliseconds
+ "updated_at": "1723411698506" // unix timestamp in milliseconds
+ }
+ }]
+}
+```
+
+
\ No newline at end of file
diff --git a/evaluations/overview.mdx b/evaluations/overview.mdx
new file mode 100644
index 000000000..2ed1f9a90
--- /dev/null
+++ b/evaluations/overview.mdx
@@ -0,0 +1,26 @@
+---
+title: Evaluations
+---
+
+LangWatch offers an extensive library of evaluators to help you evaluate the quality and guarantee the safety of your LLM apps.
+Those are very easy to set up on [LangWatch dashboard](https://app.langwatch.com/).
+
+
+
+## Evaluators List
+
+import EvaluatorsList from "/snippets/evaluators-list.mdx"
+
+
+
+## Custom Evaluator Integration
+
+If you have a custom evaluator built in-house, you can follow the guide below to integrate.
+
+
+
+
diff --git a/favicon.svg b/favicon.svg
index 6a3233265..51069fa13 100644
--- a/favicon.svg
+++ b/favicon.svg
@@ -1,49 +1,30 @@
-