From b1781058a587ea8f74a047308cbe67b6cc5117de Mon Sep 17 00:00:00 2001 From: Karthik Kalyanaraman Date: Thu, 4 Apr 2024 00:01:40 -0700 Subject: [PATCH 01/20] Pagination bug --- components/project/eval/eval.tsx | 4 ++-- components/project/eval/prompts.tsx | 4 ++-- lib/services/trace_service.ts | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/components/project/eval/eval.tsx b/components/project/eval/eval.tsx index 8441bfdc..7b139ddd 100644 --- a/components/project/eval/eval.tsx +++ b/components/project/eval/eval.tsx @@ -62,9 +62,9 @@ export default function Eval({ email }: { email: string }) { } if (result) { if (data) { - setData((prevData: any) => [...prevData, ...result.prompts.result]); + setData((prevData: any) => [...prevData, ...result?.prompts?.result || []]); } else { - setData(result.prompts.result); + setData(result?.prompts?.result || []); } } setPage((currentPage) => currentPage + 1); diff --git a/components/project/eval/prompts.tsx b/components/project/eval/prompts.tsx index bb385183..9ea37d51 100644 --- a/components/project/eval/prompts.tsx +++ b/components/project/eval/prompts.tsx @@ -52,9 +52,9 @@ export default function Prompts({ email }: { email: string }) { } if (result) { if (data) { - setData((prevData: any) => [...prevData, ...result.prompts.result]); + setData((prevData: any) => [...prevData, ...result?.prompts?.result || []]); } else { - setData(result.prompts.result); + setData(result?.prompts?.result || []); } } setPage((currentPage) => currentPage + 1); diff --git a/lib/services/trace_service.ts b/lib/services/trace_service.ts index 1761aa06..ad7c35c7 100644 --- a/lib/services/trace_service.ts +++ b/lib/services/trace_service.ts @@ -244,7 +244,7 @@ export class TraceService implements ITraceService { const md = { page, page_size: pageSize, total_pages: totalPages }; if (page! > totalPages) { - throw Error("Page number is greater than total pages"); + page = totalPages; } const query = sql.select( `* FROM ${project_id} WHERE attributes LIKE '%${attribute}%' ORDER BY 'start_time' DESC LIMIT ${pageSize} OFFSET ${ @@ -325,7 +325,7 @@ export class TraceService implements ITraceService { const md = { page, page_size: pageSize, total_pages: totalPages }; if (page! > totalPages) { - throw Error("Page number is greater than total pages"); + page = totalPages; } const query = sql.select( `* FROM ${project_id} ORDER BY 'createdAt' DESC LIMIT ${pageSize} OFFSET ${ From 0e963e226af17ffdba6282496d1979c6e30c20ad Mon Sep 17 00:00:00 2001 From: Karthik Kalyanaraman Date: Thu, 4 Apr 2024 17:13:49 -0700 Subject: [PATCH 02/20] Bug fix --- app/api/user/route.ts | 1 - components/project/traces.tsx | 2 -- lib/utils.ts | 1 + 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/app/api/user/route.ts b/app/api/user/route.ts index d7e95f34..a10d34bf 100644 --- a/app/api/user/route.ts +++ b/app/api/user/route.ts @@ -83,7 +83,6 @@ export async function PUT(req: NextRequest) { } if ("status" in data) { - console.log("updating status"); const user = await prisma.user.update({ where: { id, diff --git a/components/project/traces.tsx b/components/project/traces.tsx index 523aa352..1f56c03e 100644 --- a/components/project/traces.tsx +++ b/components/project/traces.tsx @@ -80,8 +80,6 @@ export default function Traces({ email }: { email: string }) { } // Merge the new data with the existing data - console.log("currentData", currentData); - console.log("newData", newData); if (currentData.length > 0) { const updatedData = [...currentData, ...newData]; diff --git a/lib/utils.ts b/lib/utils.ts index 584d22f2..2c6fd519 100644 --- a/lib/utils.ts +++ b/lib/utils.ts @@ -326,6 +326,7 @@ export function calculatePriceFromUsage( output_tokens: number; } ): any { + if (!model) return { total: 0, input: 0, output: 0 }; if (vendor === "openai") { const costTable = OPENAI_PRICING[model.includes("gpt-4") ? "gpt-4" : model]; if (costTable) { From 740a3d6f0762d15fda5c963b0a68e2d304972c6f Mon Sep 17 00:00:00 2001 From: Karthik Kalyanaraman Date: Mon, 20 May 2024 19:24:26 -0700 Subject: [PATCH 03/20] Update package --- package-lock.json | 85 ++++++++++++++++++++++++----------------------- 1 file changed, 44 insertions(+), 41 deletions(-) diff --git a/package-lock.json b/package-lock.json index 002227e2..3788e87a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -64,7 +64,7 @@ "lucide-react": "^0.323.0", "mammoth": "^1.7.0", "markdown-it": "^14.0.0", - "next": "14.1.0", + "next": "14.1.1", "next-auth": "^4.24.5", "next-themes": "^0.2.1", "npm": "^10.7.0", @@ -1489,8 +1489,9 @@ } }, "node_modules/@next/env": { - "version": "14.1.0", - "license": "MIT" + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/@next/env/-/env-14.1.1.tgz", + "integrity": "sha512-7CnQyD5G8shHxQIIg3c7/pSeYFeMhsNbpU/bmvH7ZnDql7mNRgg8O2JZrhrc/soFnfBnKP4/xXNiiSIPn2w8gA==" }, "node_modules/@next/eslint-plugin-next": { "version": "14.1.0", @@ -1501,11 +1502,12 @@ } }, "node_modules/@next/swc-darwin-arm64": { - "version": "14.1.0", + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.1.1.tgz", + "integrity": "sha512-yDjSFKQKTIjyT7cFv+DqQfW5jsD+tVxXTckSe1KIouKk75t1qZmj/mV3wzdmFb0XHVGtyRjDMulfVG8uCKemOQ==", "cpu": [ "arm64" ], - "license": "MIT", "optional": true, "os": [ "darwin" @@ -1515,9 +1517,9 @@ } }, "node_modules/@next/swc-darwin-x64": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.1.0.tgz", - "integrity": "sha512-1jgudN5haWxiAl3O1ljUS2GfupPmcftu2RYJqZiMJmmbBT5M1XDffjUtRUzP4W3cBHsrvkfOFdQ71hAreNQP6g==", + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.1.1.tgz", + "integrity": "sha512-KCQmBL0CmFmN8D64FHIZVD9I4ugQsDBBEJKiblXGgwn7wBCSe8N4Dx47sdzl4JAg39IkSN5NNrr8AniXLMb3aw==", "cpu": [ "x64" ], @@ -1530,9 +1532,9 @@ } }, "node_modules/@next/swc-linux-arm64-gnu": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.1.0.tgz", - "integrity": "sha512-RHo7Tcj+jllXUbK7xk2NyIDod3YcCPDZxj1WLIYxd709BQ7WuRYl3OWUNG+WUfqeQBds6kvZYlc42NJJTNi4tQ==", + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.1.1.tgz", + "integrity": "sha512-YDQfbWyW0JMKhJf/T4eyFr4b3tceTorQ5w2n7I0mNVTFOvu6CGEzfwT3RSAQGTi/FFMTFcuspPec/7dFHuP7Eg==", "cpu": [ "arm64" ], @@ -1545,9 +1547,9 @@ } }, "node_modules/@next/swc-linux-arm64-musl": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.1.0.tgz", - "integrity": "sha512-v6kP8sHYxjO8RwHmWMJSq7VZP2nYCkRVQ0qolh2l6xroe9QjbgV8siTbduED4u0hlk0+tjS6/Tuy4n5XCp+l6g==", + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.1.1.tgz", + "integrity": "sha512-fiuN/OG6sNGRN/bRFxRvV5LyzLB8gaL8cbDH5o3mEiVwfcMzyE5T//ilMmaTrnA8HLMS6hoz4cHOu6Qcp9vxgQ==", "cpu": [ "arm64" ], @@ -1560,9 +1562,9 @@ } }, "node_modules/@next/swc-linux-x64-gnu": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.1.0.tgz", - "integrity": "sha512-zJ2pnoFYB1F4vmEVlb/eSe+VH679zT1VdXlZKX+pE66grOgjmKJHKacf82g/sWE4MQ4Rk2FMBCRnX+l6/TVYzQ==", + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.1.1.tgz", + "integrity": "sha512-rv6AAdEXoezjbdfp3ouMuVqeLjE1Bin0AuE6qxE6V9g3Giz5/R3xpocHoAi7CufRR+lnkuUjRBn05SYJ83oKNQ==", "cpu": [ "x64" ], @@ -1575,9 +1577,9 @@ } }, "node_modules/@next/swc-linux-x64-musl": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.1.0.tgz", - "integrity": "sha512-rbaIYFt2X9YZBSbH/CwGAjbBG2/MrACCVu2X0+kSykHzHnYH5FjHxwXLkcoJ10cX0aWCEynpu+rP76x0914atg==", + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.1.1.tgz", + "integrity": "sha512-YAZLGsaNeChSrpz/G7MxO3TIBLaMN8QWMr3X8bt6rCvKovwU7GqQlDu99WdvF33kI8ZahvcdbFsy4jAFzFX7og==", "cpu": [ "x64" ], @@ -1590,9 +1592,9 @@ } }, "node_modules/@next/swc-win32-arm64-msvc": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.1.0.tgz", - "integrity": "sha512-o1N5TsYc8f/HpGt39OUQpQ9AKIGApd3QLueu7hXk//2xq5Z9OxmV6sQfNp8C7qYmiOlHYODOGqNNa0e9jvchGQ==", + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.1.1.tgz", + "integrity": "sha512-1L4mUYPBMvVDMZg1inUYyPvFSduot0g73hgfD9CODgbr4xiTYe0VOMTZzaRqYJYBA9mana0x4eaAaypmWo1r5A==", "cpu": [ "arm64" ], @@ -1605,9 +1607,9 @@ } }, "node_modules/@next/swc-win32-ia32-msvc": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.1.0.tgz", - "integrity": "sha512-XXIuB1DBRCFwNO6EEzCTMHT5pauwaSj4SWs7CYnME57eaReAKBXCnkUE80p/pAZcewm7hs+vGvNqDPacEXHVkw==", + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.1.1.tgz", + "integrity": "sha512-jvIE9tsuj9vpbbXlR5YxrghRfMuG0Qm/nZ/1KDHc+y6FpnZ/apsgh+G6t15vefU0zp3WSpTMIdXRUsNl/7RSuw==", "cpu": [ "ia32" ], @@ -1620,9 +1622,9 @@ } }, "node_modules/@next/swc-win32-x64-msvc": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.1.0.tgz", - "integrity": "sha512-9WEbVRRAqJ3YFVqEZIxUqkiO8l1nool1LmNxygr5HWF8AcSYsEpneUDhmjUVJEzO2A04+oPtZdombzzPPkTtgg==", + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.1.1.tgz", + "integrity": "sha512-S6K6EHDU5+1KrBDLko7/c1MNy/Ya73pIAmvKeFwsF4RmBFJSO7/7YeD4FnZ4iBdzE69PpQ4sOMU9ORKeNuxe8A==", "cpu": [ "x64" ], @@ -8917,10 +8919,11 @@ } }, "node_modules/next": { - "version": "14.1.0", - "license": "MIT", + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/next/-/next-14.1.1.tgz", + "integrity": "sha512-McrGJqlGSHeaz2yTRPkEucxQKe5Zq7uPwyeHNmJaZNY4wx9E9QdxmTp310agFRoMuIYgQrCrT3petg13fSVOww==", "dependencies": { - "@next/env": "14.1.0", + "@next/env": "14.1.1", "@swc/helpers": "0.5.2", "busboy": "1.6.0", "caniuse-lite": "^1.0.30001579", @@ -8935,15 +8938,15 @@ "node": ">=18.17.0" }, "optionalDependencies": { - "@next/swc-darwin-arm64": "14.1.0", - "@next/swc-darwin-x64": "14.1.0", - "@next/swc-linux-arm64-gnu": "14.1.0", - "@next/swc-linux-arm64-musl": "14.1.0", - "@next/swc-linux-x64-gnu": "14.1.0", - "@next/swc-linux-x64-musl": "14.1.0", - "@next/swc-win32-arm64-msvc": "14.1.0", - "@next/swc-win32-ia32-msvc": "14.1.0", - "@next/swc-win32-x64-msvc": "14.1.0" + "@next/swc-darwin-arm64": "14.1.1", + "@next/swc-darwin-x64": "14.1.1", + "@next/swc-linux-arm64-gnu": "14.1.1", + "@next/swc-linux-arm64-musl": "14.1.1", + "@next/swc-linux-x64-gnu": "14.1.1", + "@next/swc-linux-x64-musl": "14.1.1", + "@next/swc-win32-arm64-msvc": "14.1.1", + "@next/swc-win32-ia32-msvc": "14.1.1", + "@next/swc-win32-x64-msvc": "14.1.1" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", From 3aa05284904e3959e57e9d37bd452de7124df2f9 Mon Sep 17 00:00:00 2001 From: Karthik Kalyanaraman Date: Sat, 15 Jun 2024 23:28:22 -0700 Subject: [PATCH 04/20] Bugfixes --- components/project/traces/trace-row.tsx | 35 +++++++----- components/shared/vendor-metadata.tsx | 72 +++++++++++++++++++++++- lib/utils.ts | 2 + public/dspy.png | Bin 0 -> 11508 bytes public/pg.png | Bin 0 -> 21641 bytes public/weaviate.png | Bin 0 -> 9130 bytes 6 files changed, 93 insertions(+), 16 deletions(-) create mode 100644 public/dspy.png create mode 100644 public/pg.png create mode 100644 public/weaviate.png diff --git a/components/project/traces/trace-row.tsx b/components/project/traces/trace-row.tsx index 660a2a98..09e55b32 100644 --- a/components/project/traces/trace-row.tsx +++ b/components/project/traces/trace-row.tsx @@ -6,7 +6,7 @@ import { convertTracesToHierarchy, correctTimestampFormat, } from "@/lib/trace_utils"; -import { calculatePriceFromUsage, formatDateTime } from "@/lib/utils"; +import { calculatePriceFromUsage, cn, formatDateTime } from "@/lib/utils"; import { ChevronDown, ChevronRight } from "lucide-react"; import { useState } from "react"; import { JsonView, allExpanded, defaultStyles } from "react-json-view-lite"; @@ -104,11 +104,10 @@ export const TraceRow = ({ return (
setCollapsed(!collapsed)} >
@@ -149,14 +148,22 @@ export const TraceRow = ({

{model}

- 0 ? JSON.parse(prompts[0]) : []} - className="flex items-center max-w-fit text-xs h-10 truncate overflow-y-scroll font-semibold col-span-2" - /> - 0 ? JSON.parse(responses[0]) : []} - className="flex items-center max-w-fit text-xs h-10 truncate overflow-y-scroll font-semibold col-span-2" - /> + {prompts?.length > 0 ? ( + + ) : ( +

+ )} + {responses?.length > 0 ? ( + + ) : ( +

+ )}

{userId}

{tokenCounts?.input_tokens || tokenCounts?.prompt_tokens} diff --git a/components/shared/vendor-metadata.tsx b/components/shared/vendor-metadata.tsx index cd5d040c..e85de789 100644 --- a/components/shared/vendor-metadata.tsx +++ b/components/shared/vendor-metadata.tsx @@ -46,8 +46,16 @@ export function vendorBadgeColor(vendor: string) { return "bg-grey-500"; } - if (vendor.includes("qdrant")) { - return "bg-grey-500"; + if (vendor.includes("dspy")) { + return "bg-red-500"; + } + + if (vendor.includes("weaviate")) { + return "bg-green-500"; + } + + if (vendor.includes("pg")) { + return "bg-blue-500"; } return "bg-gray-500"; @@ -98,6 +106,18 @@ export function vendorColor(vendor: string) { return "bg-slate-200"; } + if (vendor.includes("dspy")) { + return "bg-red-200"; + } + + if (vendor.includes("weaviate")) { + return "bg-green-200"; + } + + if (vendor.includes("pg")) { + return "bg-blue-200"; + } + return "bg-gray-800"; } @@ -279,6 +299,54 @@ export function VendorLogo({ ); } + if (vendor.includes("dspy")) { + const color = vendorColor("dspy"); + return ( + DSPy Logo + ); + } + + if (vendor.includes("weaviate")) { + const color = vendorColor("weaviate"); + return ( + Weaviate Logo + ); + } + + if (vendor.includes("pg")) { + const color = vendorColor("pg"); + return ( + Postgres Logo + ); + } + return (

XGG0Kg}H3t?de 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 literal 0 HcmV?d00001 diff --git a/public/pg.png b/public/pg.png new file mode 100644 index 0000000000000000000000000000000000000000..79ddb82ff478163d0a6b35b18c0dfdd16407ee74 GIT binary patch literal 21641 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 literal 0 HcmV?d00001 diff --git a/public/weaviate.png b/public/weaviate.png new file mode 100644 index 0000000000000000000000000000000000000000..790233f667857479ad9cb5eab663f5f48e39bede GIT binary patch literal 9130 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 literal 0 HcmV?d00001 From 653cbf9ed4421e8f8cfa9632ea9ff745a241fd2b Mon Sep 17 00:00:00 2001 From: Karthik Kalyanaraman Date: Wed, 3 Jul 2024 13:57:53 -0700 Subject: [PATCH 05/20] Add migration file --- .../20240703205722_add_ext_expires_in_to_account/migration.sql | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 prisma/migrations/20240703205722_add_ext_expires_in_to_account/migration.sql diff --git a/prisma/migrations/20240703205722_add_ext_expires_in_to_account/migration.sql b/prisma/migrations/20240703205722_add_ext_expires_in_to_account/migration.sql new file mode 100644 index 00000000..1c3acf40 --- /dev/null +++ b/prisma/migrations/20240703205722_add_ext_expires_in_to_account/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE "Account" ADD COLUMN "ext_expires_in" INTEGER; From ea5ae6a61c5bf81bdaff2106de5475eaeafd2a89 Mon Sep 17 00:00:00 2001 From: dylan Date: Thu, 5 Sep 2024 14:38:36 -0400 Subject: [PATCH 06/20] adding ability to add to dataset from traces tab --- components/project/traces/trace-sheet.tsx | 90 +++++++++++++++++++++- components/project/traces/traces-table.tsx | 1 + 2 files changed, 90 insertions(+), 1 deletion(-) diff --git a/components/project/traces/trace-sheet.tsx b/components/project/traces/trace-sheet.tsx index 45bce7f8..a5e83efe 100644 --- a/components/project/traces/trace-sheet.tsx +++ b/components/project/traces/trace-sheet.tsx @@ -1,3 +1,4 @@ +import { AddtoDataset } from "@/components/shared/add-to-dataset"; import ConversationView from "@/components/shared/conversation-view"; import LanggraphView from "@/components/shared/langgraph-view"; import TraceGraph, { AttributesTabs } from "@/components/traces/trace_graph"; @@ -25,10 +26,12 @@ import { import { useEffect, useState } from "react"; export function TraceSheet({ + project_id, trace, open, setOpen, }: { + project_id: string; trace: Trace; open: boolean; setOpen: (open: boolean) => void; @@ -52,6 +55,84 @@ export function TraceSheet({ setSelectedVendors(trace.vendors); if (trace.vendors.includes("langgraph")) setIncludesLanggraph(true); if (!open) setSpansView("SPANS"); + + // const spanId = row.original.span_id; + // const prompts = row.getValue("input") as string[]; + // const responses = row.getValue("output") as string[]; + // const model = row.getValue("model") as string; + + // let input = ""; + // if (prompts && prompts.length > 0) { + // // get last item in prompts + // const lastItem = prompts[prompts.length - 1]; + // const parsedLastItem = JSON.parse(lastItem); + // input = + // parsedLastItem[parsedLastItem.length - 1]?.content || + // parsedLastItem[parsedLastItem.length - 1]?.message?.content || + // parsedLastItem[parsedLastItem.length - 1]?.text; + + // // check if input is not a string + // if (typeof input !== "string") { + // input = JSON.stringify(input); + // } + // } + + // let output = ""; + // if (responses && responses.length > 0) { + // // get last item in responses + // const lastItem = responses[responses.length - 1]; + // const parsedLastItem = JSON.parse(lastItem); + // output = + // parsedLastItem[parsedLastItem.length - 1]?.message?.content || + // parsedLastItem[parsedLastItem.length - 1]?.text || + // parsedLastItem[parsedLastItem.length - 1]?.content; + + // // check if output is not a string + // if (typeof output !== "string") { + // output = JSON.stringify(output); + // } + // } + }, [trace, open]); + + useEffect(() => { + if (span) { + const spanId = row.original.span_id; + const prompts = row.getValue("input") as string[]; + const responses = row.getValue("output") as string[]; + const model = row.getValue("model") as string; + + let input = ""; + if (prompts && prompts.length > 0) { + // get last item in prompts + const lastItem = prompts[prompts.length - 1]; + const parsedLastItem = JSON.parse(lastItem); + input = + parsedLastItem[parsedLastItem.length - 1]?.content || + parsedLastItem[parsedLastItem.length - 1]?.message?.content || + parsedLastItem[parsedLastItem.length - 1]?.text; + + // check if input is not a string + if (typeof input !== "string") { + input = JSON.stringify(input); + } + } + + let output = ""; + if (responses && responses.length > 0) { + // get last item in responses + const lastItem = responses[responses.length - 1]; + const parsedLastItem = JSON.parse(lastItem); + output = + parsedLastItem[parsedLastItem.length - 1]?.message?.content || + parsedLastItem[parsedLastItem.length - 1]?.text || + parsedLastItem[parsedLastItem.length - 1]?.content; + + // check if output is not a string + if (typeof output !== "string") { + output = JSON.stringify(output); + } + } + } }, [trace, open]); return ( @@ -93,12 +174,19 @@ export function TraceSheet({ Back
+ {/* */} - + Create Dataset diff --git a/components/project/traces/trace-sheet.tsx b/components/project/traces/trace-sheet.tsx index a5e83efe..95777f1f 100644 --- a/components/project/traces/trace-sheet.tsx +++ b/components/project/traces/trace-sheet.tsx @@ -25,6 +25,12 @@ import { } from "lucide-react"; import { useEffect, useState } from "react"; +interface CheckedData { + input: string; + output: string; + spanId: string; +} + export function TraceSheet({ project_id, trace, @@ -49,96 +55,56 @@ export function TraceSheet({ const [span, setSpan] = useState(null); const [attributes, setAttributes] = useState(null); const [events, setEvents] = useState(null); + const [selectedData, setSelectedData] = useState([]); useEffect(() => { setSelectedTrace(trace.trace_hierarchy); setSelectedVendors(trace.vendors); if (trace.vendors.includes("langgraph")) setIncludesLanggraph(true); - if (!open) setSpansView("SPANS"); - - // const spanId = row.original.span_id; - // const prompts = row.getValue("input") as string[]; - // const responses = row.getValue("output") as string[]; - // const model = row.getValue("model") as string; - - // let input = ""; - // if (prompts && prompts.length > 0) { - // // get last item in prompts - // const lastItem = prompts[prompts.length - 1]; - // const parsedLastItem = JSON.parse(lastItem); - // input = - // parsedLastItem[parsedLastItem.length - 1]?.content || - // parsedLastItem[parsedLastItem.length - 1]?.message?.content || - // parsedLastItem[parsedLastItem.length - 1]?.text; - - // // check if input is not a string - // if (typeof input !== "string") { - // input = JSON.stringify(input); - // } - // } - - // let output = ""; - // if (responses && responses.length > 0) { - // // get last item in responses - // const lastItem = responses[responses.length - 1]; - // const parsedLastItem = JSON.parse(lastItem); - // output = - // parsedLastItem[parsedLastItem.length - 1]?.message?.content || - // parsedLastItem[parsedLastItem.length - 1]?.text || - // parsedLastItem[parsedLastItem.length - 1]?.content; - - // // check if output is not a string - // if (typeof output !== "string") { - // output = JSON.stringify(output); - // } - // } + if (!open) { + setSelectedData([]); + setSpansView("SPANS"); + } }, [trace, open]); useEffect(() => { if (span) { - const spanId = row.original.span_id; - const prompts = row.getValue("input") as string[]; - const responses = row.getValue("output") as string[]; - const model = row.getValue("model") as string; - + const spanId = span.span_id; + const prompts = span?.input || []; + const responses = span?.output || []; let input = ""; + let output = ""; + if (prompts && prompts.length > 0) { - // get last item in prompts - const lastItem = prompts[prompts.length - 1]; - const parsedLastItem = JSON.parse(lastItem); + const lastPrompt = prompts[prompts.length - 1]; input = - parsedLastItem[parsedLastItem.length - 1]?.content || - parsedLastItem[parsedLastItem.length - 1]?.message?.content || - parsedLastItem[parsedLastItem.length - 1]?.text; - - // check if input is not a string - if (typeof input !== "string") { - input = JSON.stringify(input); - } + typeof lastPrompt === "string" + ? lastPrompt + : JSON.stringify(lastPrompt); } - let output = ""; if (responses && responses.length > 0) { - // get last item in responses - const lastItem = responses[responses.length - 1]; - const parsedLastItem = JSON.parse(lastItem); + const lastResponse = responses[responses.length - 1]; output = - parsedLastItem[parsedLastItem.length - 1]?.message?.content || - parsedLastItem[parsedLastItem.length - 1]?.text || - parsedLastItem[parsedLastItem.length - 1]?.content; - - // check if output is not a string - if (typeof output !== "string") { - output = JSON.stringify(output); - } + typeof lastResponse === "string" + ? lastResponse + : JSON.stringify(lastResponse); } + + const checkedData = { + spanId, + input, + output, + }; + + setSelectedData((prev) => [...prev, checkedData]); } - }, [trace, open]); + }, [span]); return ( - + Trace Details {spansView === "SPANS" && ( @@ -174,11 +140,12 @@ export function TraceSheet({ Back
- {/* */} + selectedData={selectedData} + disabled={selectedData.length === 0} + /> - + Add to Dataset @@ -146,7 +146,7 @@ export default function DatasetCombobox({ variant="outline" role="combobox" aria-expanded={open} - className="w-[200px] justify-between" + className="w-[200px] z-[920] justify-between" > {datasetId ? fetchDatasets.data?.datasets?.find( @@ -156,7 +156,7 @@ export default function DatasetCombobox({ - + No dataset found. diff --git a/components/ui/dialog.tsx b/components/ui/dialog.tsx index 95b0d38a..a72c1548 100644 --- a/components/ui/dialog.tsx +++ b/components/ui/dialog.tsx @@ -1,18 +1,18 @@ -"use client" +"use client"; -import * as React from "react" -import * as DialogPrimitive from "@radix-ui/react-dialog" -import { Cross2Icon } from "@radix-ui/react-icons" +import * as React from "react"; +import * as DialogPrimitive from "@radix-ui/react-dialog"; +import { Cross2Icon } from "@radix-ui/react-icons"; -import { cn } from "@/lib/utils" +import { cn } from "@/lib/utils"; -const Dialog = DialogPrimitive.Root +const Dialog = DialogPrimitive.Root; -const DialogTrigger = DialogPrimitive.Trigger +const DialogTrigger = DialogPrimitive.Trigger; -const DialogPortal = DialogPrimitive.Portal +const DialogPortal = DialogPrimitive.Portal; -const DialogClose = DialogPrimitive.Close +const DialogClose = DialogPrimitive.Close; const DialogOverlay = React.forwardRef< React.ElementRef, @@ -21,13 +21,13 @@ const DialogOverlay = React.forwardRef< -)) -DialogOverlay.displayName = DialogPrimitive.Overlay.displayName +)); +DialogOverlay.displayName = DialogPrimitive.Overlay.displayName; const DialogContent = React.forwardRef< React.ElementRef, @@ -38,7 +38,7 @@ const DialogContent = React.forwardRef< -)) -DialogContent.displayName = DialogPrimitive.Content.displayName +)); +DialogContent.displayName = DialogPrimitive.Content.displayName; const DialogHeader = ({ className, @@ -64,8 +64,8 @@ const DialogHeader = ({ )} {...props} /> -) -DialogHeader.displayName = "DialogHeader" +); +DialogHeader.displayName = "DialogHeader"; const DialogFooter = ({ className, @@ -78,8 +78,8 @@ const DialogFooter = ({ )} {...props} /> -) -DialogFooter.displayName = "DialogFooter" +); +DialogFooter.displayName = "DialogFooter"; const DialogTitle = React.forwardRef< React.ElementRef, @@ -93,8 +93,8 @@ const DialogTitle = React.forwardRef< )} {...props} /> -)) -DialogTitle.displayName = DialogPrimitive.Title.displayName +)); +DialogTitle.displayName = DialogPrimitive.Title.displayName; const DialogDescription = React.forwardRef< React.ElementRef, @@ -105,8 +105,8 @@ const DialogDescription = React.forwardRef< className={cn("text-sm text-muted-foreground", className)} {...props} /> -)) -DialogDescription.displayName = DialogPrimitive.Description.displayName +)); +DialogDescription.displayName = DialogPrimitive.Description.displayName; export { Dialog, @@ -119,4 +119,4 @@ export { DialogFooter, DialogTitle, DialogDescription, -} +}; From 9baa4fcf09c0a8a3fca5bcb5bbef7ea428b080b6 Mon Sep 17 00:00:00 2001 From: dylan Date: Fri, 6 Sep 2024 16:30:12 -0400 Subject: [PATCH 08/20] fixing llm parsing, disable button for non llm traces --- components/project/traces/trace-sheet.tsx | 64 +++++++++++++++-------- 1 file changed, 41 insertions(+), 23 deletions(-) diff --git a/components/project/traces/trace-sheet.tsx b/components/project/traces/trace-sheet.tsx index 95777f1f..fe31fe5d 100644 --- a/components/project/traces/trace-sheet.tsx +++ b/components/project/traces/trace-sheet.tsx @@ -70,33 +70,51 @@ export function TraceSheet({ useEffect(() => { if (span) { const spanId = span.span_id; - const prompts = span?.input || []; - const responses = span?.output || []; - let input = ""; - let output = ""; + const attributes = span?.attributes ? JSON.parse(span.attributes) : {}; - if (prompts && prompts.length > 0) { - const lastPrompt = prompts[prompts.length - 1]; - input = - typeof lastPrompt === "string" - ? lastPrompt - : JSON.stringify(lastPrompt); - } + let prompt: string = ""; + let response: string = ""; + if (span.events) { + const events: any[] = JSON.parse(span.events); + + const promptEvent = events.find( + (event: any) => event.name === "gen_ai.content.prompt" + ); + if ( + promptEvent && + promptEvent["attributes"] && + promptEvent["attributes"]["gen_ai.prompt"] + ) { + prompt = promptEvent["attributes"]["gen_ai.prompt"]; + } - if (responses && responses.length > 0) { - const lastResponse = responses[responses.length - 1]; - output = - typeof lastResponse === "string" - ? lastResponse - : JSON.stringify(lastResponse); + const responseEvent = events.find( + (event: any) => event.name === "gen_ai.content.completion" + ); + if ( + responseEvent && + responseEvent["attributes"] && + responseEvent["attributes"]["gen_ai.completion"] + ) { + response = responseEvent["attributes"]["gen_ai.completion"]; + } + } + if (attributes["llm.prompts"] && attributes["llm.responses"]) { + prompt = attributes["llm.prompts"]; + response = attributes["llm.responses"]; } + const inputData = prompt ? JSON.parse(prompt) : []; + const outputData = response ? JSON.parse(response) : []; + + const input = inputData.length > 0 ? inputData[0].content : ""; + const output = outputData.length > 0 ? outputData[0].content : ""; + const checkedData = { spanId, input, output, }; - setSelectedData((prev) => [...prev, checkedData]); } }, [span]); @@ -141,19 +159,19 @@ export function TraceSheet({
data.input || data.output) + } />
@@ -658,12 +664,6 @@ export default function LLMChat({ {!busy && } )} - {(cost || latency) && ( -
-

{`Cost: ${cost}`}

-

{`Latency: ${latency}ms`}

-
- )} ); } diff --git a/components/shared/llm-view.tsx b/components/shared/llm-view.tsx index 3c45fd5b..7122ad91 100644 --- a/components/shared/llm-view.tsx +++ b/components/shared/llm-view.tsx @@ -8,60 +8,71 @@ import { v4 as uuidv4 } from "uuid"; import { Button } from "../ui/button"; export const LLMView = ({ - prompts, - responses, + prompts = [], + responses = [], setMessages, Evaluate = () => null, doPiiDetection = false, importTrace = false, }: { - prompts: any; - responses: any; + prompts?: any; + responses?: any; setMessages?: (messages: any[]) => void; Evaluate?: React.FC; doPiiDetection?: boolean; importTrace?: boolean; }) => { const [selectedTab, setSelectedTab] = useState(0); + + const hasPrompts = prompts.length > 0; + const hasResponses = responses.length > 0; + return (
- {prompts.map((prompt: any, i: number) => ( + {(hasPrompts ? prompts : responses).map((_: any, i: number) => ( ))} - {importTrace && ( + {importTrace && (hasPrompts || hasResponses) && ( )}
- {prompts?.length > 0 && typeof JSON.parse(prompts[selectedTab]) === "object" && + + {/* Render Prompts */} + {hasPrompts && + typeof JSON.parse(prompts[selectedTab]) === "object" && JSON.parse(prompts[selectedTab]).map((prompt: any, i: number) => { let role; let content; - // check if prompt is a list if (Array.isArray(prompt) && prompt.length > 0) { role = prompt[0]?.role ? prompt[0]?.role?.toLowerCase() : "User"; content = prompt[0]?.content ? prompt[0]?.content : prompt[0]?.function_call - ? prompt[0]?.function_call - : ""; + ? prompt[0]?.function_call + : ""; } else { role = prompt?.role ? prompt?.role?.toLowerCase() : "User"; content = prompt?.content ? prompt?.content : prompt?.function_call - ? prompt?.function_call - : ""; + ? prompt?.function_call + : ""; } - // will add once edit image wrapper has been added in sdks - // const url = prompt?.content?.url; - // const b64Json = prompt?.content?.b64_json; - // const revisedPrompt = prompt?.content?.revised_prompt; return (
); })} - {responses?.length > 0 && responses[selectedTab] && typeof JSON.parse(responses[selectedTab]) === "object" && + + {/* Render Responses */} + {hasResponses && + typeof JSON.parse(responses[selectedTab]) === "object" && JSON.parse(responses[selectedTab]).map((response: any, i: number) => { const role = response?.role?.toLowerCase() || @@ -131,7 +143,6 @@ export const LLMView = ({ const url = response?.content?.url; const b64Json = response?.content?.b64_json; const revisedPrompt = response?.content?.revised_prompt; - // const isPicture = url || b64Json; return (
, @@ -24,8 +24,8 @@ const AlertDialogOverlay = React.forwardRef< {...props} ref={ref} /> -)) -AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName +)); +AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName; const AlertDialogContent = React.forwardRef< React.ElementRef, @@ -36,14 +36,14 @@ const AlertDialogContent = React.forwardRef< -)) -AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName +)); +AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName; const AlertDialogHeader = ({ className, @@ -56,8 +56,8 @@ const AlertDialogHeader = ({ )} {...props} /> -) -AlertDialogHeader.displayName = "AlertDialogHeader" +); +AlertDialogHeader.displayName = "AlertDialogHeader"; const AlertDialogFooter = ({ className, @@ -70,8 +70,8 @@ const AlertDialogFooter = ({ )} {...props} /> -) -AlertDialogFooter.displayName = "AlertDialogFooter" +); +AlertDialogFooter.displayName = "AlertDialogFooter"; const AlertDialogTitle = React.forwardRef< React.ElementRef, @@ -82,8 +82,8 @@ const AlertDialogTitle = React.forwardRef< className={cn("text-lg font-semibold", className)} {...props} /> -)) -AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName +)); +AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName; const AlertDialogDescription = React.forwardRef< React.ElementRef, @@ -94,9 +94,9 @@ const AlertDialogDescription = React.forwardRef< className={cn("text-sm text-muted-foreground", className)} {...props} /> -)) +)); AlertDialogDescription.displayName = - AlertDialogPrimitive.Description.displayName + AlertDialogPrimitive.Description.displayName; const AlertDialogAction = React.forwardRef< React.ElementRef, @@ -107,8 +107,8 @@ const AlertDialogAction = React.forwardRef< className={cn(buttonVariants(), className)} {...props} /> -)) -AlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName +)); +AlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName; const AlertDialogCancel = React.forwardRef< React.ElementRef, @@ -123,8 +123,8 @@ const AlertDialogCancel = React.forwardRef< )} {...props} /> -)) -AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName +)); +AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName; export { AlertDialog, @@ -138,4 +138,4 @@ export { AlertDialogDescription, AlertDialogAction, AlertDialogCancel, -} +}; diff --git a/lib/constants.ts b/lib/constants.ts index 10f5e22e..89802fb0 100644 --- a/lib/constants.ts +++ b/lib/constants.ts @@ -199,12 +199,12 @@ export const COHERE_PRICING: Record = { output: 0.002, }, "command-r": { - input: 0.0005, - output: 0.0015, + input: 0.00015, + output: 0.0006, }, "command-r-plus": { - input: 0.003, - output: 0.015, + input: 0.0025, + output: 0.01, }, }; From e6ece07d1c3140e3615ee911d19a0d93ce69e5aa Mon Sep 17 00:00:00 2001 From: dylanzuber-scale3 <116033320+dylanzuber-scale3@users.noreply.github.com> Date: Tue, 10 Sep 2024 13:30:04 -0400 Subject: [PATCH 11/20] adding api key auth to create project api key (#270) --- app/api/api-key/route.ts | 10 ++++++- package-lock.json | 62 +++++++++++++++++++++++++--------------- 2 files changed, 48 insertions(+), 24 deletions(-) diff --git a/app/api/api-key/route.ts b/app/api/api-key/route.ts index 239c51e1..137a9f2a 100644 --- a/app/api/api-key/route.ts +++ b/app/api/api-key/route.ts @@ -1,6 +1,6 @@ import { authOptions } from "@/lib/auth/options"; import prisma from "@/lib/prisma"; -import { generateApiKey, hashApiKey } from "@/lib/utils"; +import { generateApiKey, hashApiKey, authApiKey } from "@/lib/utils"; import { getServerSession } from "next-auth"; import { redirect } from "next/navigation"; import { NextRequest, NextResponse } from "next/server"; @@ -9,6 +9,14 @@ import { NextRequest, NextResponse } from "next/server"; export async function POST(req: NextRequest) { const projectId = req.nextUrl.searchParams.get("project_id") as string; const teamId = req.nextUrl.searchParams.get("team_id") as string; + // if user is generating an api key for their project through the api + const projectGenApiKey = req.headers.get("x-api-key"); + if (projectGenApiKey !== null) { + const response = await authApiKey(projectGenApiKey, true); + if (response.status !== 200) { + return response; + } + } if (!projectId && !teamId) { return NextResponse.json( diff --git a/package-lock.json b/package-lock.json index 78c9f102..20b8e6a6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,8 +19,8 @@ "@headlessui/react": "^1.7.18", "@headlessui/tailwindcss": "^0.2.0", "@hookform/resolvers": "^3.3.4", - "@langtrase/trace-attributes": "^6.0.5", - "@langtrase/typescript-sdk": "^3.3.2", + "@langtrase/trace-attributes": "^7.0.1", + "@langtrase/typescript-sdk": "^5.0.1", "@mui/icons-material": "^5.15.14", "@mui/material": "^5.15.14", "@mui/x-tree-view": "^6.17.0", @@ -1893,6 +1893,8 @@ "node_modules/@graphql-typed-document-node/core": { "version": "3.2.0", "license": "MIT", + "optional": true, + "peer": true, "peerDependencies": { "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } @@ -2146,36 +2148,32 @@ } }, "node_modules/@langtrase/trace-attributes": { - "version": "6.0.6", - "license": "MIT", + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/@langtrase/trace-attributes/-/trace-attributes-7.3.0.tgz", + "integrity": "sha512-AbBwRT/0RZ36sNZZRLWgV7ELLz537dyO99Uj8m0Nm2ToH58LYLa+ESYaBVv9x7Wro28yUlu/yOi4ZwXjI2L9Qg==", "dependencies": { + "js-tiktoken": "^1.0.14", "json-schema-to-typescript": "^14.1.0", "ncp": "^2.0.0", - "tiktoken": "^1.0.15", "typescript": "^5.5.3" } }, "node_modules/@langtrase/typescript-sdk": { - "version": "3.3.3", - "license": "Apache-2.0", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@langtrase/typescript-sdk/-/typescript-sdk-5.3.1.tgz", + "integrity": "sha512-vQrqWGG5/asTyYqSksMgqWPxerwiTJGZR8QVneBHt2k9GSDfjbGNDAC1JnNUtSshcQIYIuJW5O8arLiXah75Hg==", "dependencies": { - "@langtrase/trace-attributes": "^5.0.1", + "@langtrase/trace-attributes": "7.3.0", "@opentelemetry/api": "^1.7.0", "@opentelemetry/instrumentation": "^0.49.1", "@opentelemetry/sdk-trace-base": "^1.22.0", "@opentelemetry/sdk-trace-node": "^1.22.0", + "@types/webpack": "^5.28.5", "ansi-colors": "^4.1.3", "axios": "^1.6.7", + "js-tiktoken": "^1.0.14", "node-loader": "^2.0.0", - "tiktoken": "^1.0.15", - "weaviate-ts-client": "^2.2.0" - } - }, - "node_modules/@langtrase/typescript-sdk/node_modules/@langtrase/trace-attributes": { - "version": "5.0.4", - "license": "MIT", - "dependencies": { - "ncp": "^2.0.0" + "npm": "^10.8.2" } }, "node_modules/@mui/base": { @@ -4959,6 +4957,16 @@ "version": "9.0.8", "license": "MIT" }, + "node_modules/@types/webpack": { + "version": "5.28.5", + "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-5.28.5.tgz", + "integrity": "sha512-wR87cgvxj3p6D0Crt1r5avwqffqPXUkNlnQ1mjU93G7gCuFjufZR4I6j8cz5g1F1tTYpfOOFvly+cmIQwL9wvw==", + "dependencies": { + "@types/node": "*", + "tapable": "^2.2.0", + "webpack": "^5" + } + }, "node_modules/@typescript-eslint/parser": { "version": "6.21.0", "dev": true, @@ -6597,6 +6605,8 @@ "node_modules/cross-fetch": { "version": "3.1.8", "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "node-fetch": "^2.6.12" } @@ -8014,6 +8024,8 @@ "node_modules/extract-files": { "version": "9.0.0", "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": "^10.17.0 || ^12.0.0 || >= 13.7.0" }, @@ -8511,6 +8523,7 @@ "node_modules/graphql": { "version": "16.9.0", "license": "MIT", + "optional": true, "peer": true, "engines": { "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" @@ -8519,6 +8532,8 @@ "node_modules/graphql-request": { "version": "5.2.0", "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "@graphql-typed-document-node/core": "^3.1.1", "cross-fetch": "^3.1.5", @@ -8532,6 +8547,8 @@ "node_modules/graphql-request/node_modules/form-data": { "version": "3.0.1", "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -9529,8 +9546,9 @@ "license": "MIT" }, "node_modules/js-tiktoken": { - "version": "1.0.12", - "license": "MIT", + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/js-tiktoken/-/js-tiktoken-1.0.14.tgz", + "integrity": "sha512-Pk3l3WOgM9joguZY2k52+jH82RtABRgB5RdGFZNUGbOKGMVlNmafcPA3b0ITcCZPu1L9UclP1tne6aw7ZI4Myg==", "dependencies": { "base64-js": "^1.5.1" } @@ -16751,10 +16769,6 @@ "node": ">=0.8" } }, - "node_modules/tiktoken": { - "version": "1.0.15", - "license": "MIT" - }, "node_modules/timers-ext": { "version": "0.1.8", "license": "ISC", @@ -17420,6 +17434,8 @@ "node_modules/weaviate-ts-client": { "version": "2.2.0", "license": "SEE LICENSE IN LICENSE", + "optional": true, + "peer": true, "dependencies": { "graphql-request": "^5.2.0", "uuid": "^9.0.1" From 27b013305e94eb05ff17f18cfb3438d3ca8d3fa1 Mon Sep 17 00:00:00 2001 From: dylanzuber-scale3 <116033320+dylanzuber-scale3@users.noreply.github.com> Date: Thu, 12 Sep 2024 11:26:10 -0400 Subject: [PATCH 12/20] Improvements to prompt playground (#272) * fixing static text area, fixing overlap * creating custo ui for playground taces * fetching traces on dialog open * fixes * fixes * fixes --------- Co-authored-by: Karthik Kalyanaraman --- .../project/[project_id]/playground/page.tsx | 2 +- components/playground/common.tsx | 20 ++- .../playground/import-trace-conversation.tsx | 125 +++++++++++++----- components/playground/llmchat.tsx | 10 +- components/project/traces/traces-table.tsx | 16 ++- components/project/traces/traces.tsx | 3 +- 6 files changed, 128 insertions(+), 48 deletions(-) diff --git a/app/(protected)/project/[project_id]/playground/page.tsx b/app/(protected)/project/[project_id]/playground/page.tsx index 103ba1e1..7a8d8cea 100644 --- a/app/(protected)/project/[project_id]/playground/page.tsx +++ b/app/(protected)/project/[project_id]/playground/page.tsx @@ -94,7 +94,7 @@ export default function Page() { settings page. -
+
{llms.map((llm: ChatInterface) => ( { + const textarea = textAreaRef.current; + if (textarea) { + textarea.style.height = "auto"; + textarea.style.height = `${textarea.scrollHeight}px`; + } + }, [value]); + const handleChange = (event: any) => { const textarea = event.target; onChange(textarea.value); @@ -81,10 +89,10 @@ export function ExpandingTextArea({ }; return ( -
+