Skip to content

Commit

Permalink
Merge branch 'development' of github.com:Scale3-Labs/langtrace into d…
Browse files Browse the repository at this point in the history
…evelopment
  • Loading branch information
karthikscale3 committed Jun 20, 2024
2 parents 76e1854 + f04abf1 commit a8678f6
Show file tree
Hide file tree
Showing 12 changed files with 714 additions and 352 deletions.
86 changes: 43 additions & 43 deletions app/(protected)/project/[project_id]/prompts/[prompt_id]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
import CreatePromptDialog from "@/components/shared/create-prompt-dialog";
import { PromptInstructions } from "@/components/shared/setup-instructions";
import { Button } from "@/components/ui/button";
import { Checkbox } from "@/components/ui/checkbox";
import { Label } from "@/components/ui/label";
import { Separator } from "@/components/ui/separator";
import { Skeleton } from "@/components/ui/skeleton";
import { Switch } from "@/components/ui/switch";
import { cn } from "@/lib/utils";
import { Prompt } from "@prisma/client";
import CodeEditor from "@uiw/react-textarea-code-editor";
Expand Down Expand Up @@ -149,6 +149,48 @@ export default function Page() {
))}
</div>
<div className="flex flex-col gap-8 w-full">
<div className="flex flex-col gap-2">
<Label>Go Live</Label>
<div className="flex items-center gap-2 w-fit">
<Switch
checked={live}
onCheckedChange={async (checked) => {
setLive(checked as boolean);
try {
const payload = {
...selectedPrompt,
live: checked,
};
await fetch("/api/prompt", {
method: "PUT",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(payload),
});
await queryClient.invalidateQueries({
queryKey: ["fetch-prompts-query", promptsetId],
});
toast.success(
checked
? "This prompt is now live"
: "This prompt is no longer live. Make sure to make another prompt live"
);
} catch (error) {
toast.error("Failed to make prompt live", {
description:
error instanceof Error
? error.message
: String(error),
});
}
}}
/>
<p className="text-sm text-muted-foreground">
Make this version of the prompt live
</p>
</div>
</div>
<div className="flex flex-col gap-2">
<Label>Prompt Registry ID</Label>
<p className="p-2 rounded-md border-2 border-muted font-semibold text-md">
Expand Down Expand Up @@ -194,48 +236,6 @@ export default function Page() {
}}
/>
</div>
<div className="flex flex-col gap-2">
<Label>Go Live</Label>
<div className="flex items-center gap-2 w-fit">
<Checkbox
checked={live}
onCheckedChange={async (checked) => {
setLive(checked as boolean);
try {
const payload = {
...selectedPrompt,
live: checked,
};
await fetch("/api/prompt", {
method: "PUT",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(payload),
});
await queryClient.invalidateQueries({
queryKey: ["fetch-prompts-query", promptsetId],
});
toast.success(
checked
? "This prompt is now live"
: "This prompt is no longer live. Make sure to make another prompt live"
);
} catch (error) {
toast.error("Failed to make prompt live", {
description:
error instanceof Error
? error.message
: String(error),
});
}
}}
/>
<p className="text-sm text-muted-foreground">
Make this version of the prompt live
</p>
</div>
</div>
<div className="flex flex-col gap-2">
<Label>Use the Live prompt directly in your code</Label>
<PromptInstructions id={promptsetId} />
Expand Down
6 changes: 0 additions & 6 deletions app/(protected)/settings/keys/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,6 @@ export default async function Page() {
if (!session || !session.user) {
redirect("/login");
}
const email = session?.user?.email as string;

const resp = await fetch(
`${process.env.NEXTAUTH_URL_INTERNAL}/api/user?email=${email}`
);
const user = await resp.json();

return (
<>
Expand Down
34 changes: 27 additions & 7 deletions app/api/promptset/route.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { authOptions } from "@/lib/auth/options";
import prisma from "@/lib/prisma";
import { authApiKey, fillPromptStringTemplate, parseQueryString } from "@/lib/utils";
import {
authApiKey,
fillPromptStringTemplate,
parseQueryString,
} from "@/lib/utils";
import { getServerSession } from "next-auth";
import { redirect } from "next/navigation";
import { NextRequest, NextResponse } from "next/server";
Expand All @@ -25,7 +29,10 @@ export async function GET(req: NextRequest) {
include: {
Prompt: {
where: {
OR: version !== undefined ? [{ version: version }] : [{ live: true }],
OR:
version !== undefined
? [{ version: version }]
: [{ live: true }],
},
},
},
Expand Down Expand Up @@ -57,26 +64,39 @@ export async function GET(req: NextRequest) {

livePromptVariables.forEach((key) => {
const value =
variables !== null ? variables[key as keyof typeof variables] ?? "" : "";
if (!variablesSet.has(`${key},${value.length > 0 ? value : "undefined"}`)) {
variables !== null
? variables[key as keyof typeof variables] ?? ""
: "";
if (
!variablesSet.has(
`${key},${value.length > 0 ? value : "undefined"}`
)
) {
errors.push(key);
}
});
if (errors.length > 0) {
const moreThanOneError = errors.length > 1;
return NextResponse.json(
{
error: `${moreThanOneError ? "Variables" : "Variable"} ${errors.join(", ")} ${moreThanOneError ? "are" : "is"} missing`,
error: `${
moreThanOneError ? "Variables" : "Variable"
} ${errors.join(", ")} ${
moreThanOneError ? "are" : "is"
} missing`,
},
{ status: 400 }
);
}
prompts[0].value = fillPromptStringTemplate(prompts[0].value, variables as Record<string, string>);
prompts[0].value = fillPromptStringTemplate(
prompts[0].value,
variables as Record<string, string>
);
}
return NextResponse.json({
...promptSet,
Prompt: undefined,
prompts: prompts
prompts: prompts,
});
} else {
const session = await getServerSession(authOptions);
Expand Down
50 changes: 41 additions & 9 deletions components/playground/common.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
"use client";

import PromptRegistryDialog from "@/components/playground/prompt-registry-dialog";
import LLMPicker from "@/components/shared/llm-picker";
import { Button } from "@/components/ui/button";
import { Separator } from "@/components/ui/separator";
import { LLM_VENDORS, LLM_VENDOR_APIS } from "@/lib/constants";
import {
CohereAIRole,
Conversation,
Expand All @@ -12,6 +11,7 @@ import {
import { cn } from "@/lib/utils";
import { ArrowTopRightIcon } from "@radix-ui/react-icons";
import { MinusCircleIcon, PlusIcon } from "lucide-react";
import Link from "next/link";
import { useEffect, useRef, useState } from "react";
import { useQuery } from "react-query";
import { toast } from "sonner";
Expand Down Expand Up @@ -84,7 +84,7 @@ export function ExpandingTextArea({
ref={textAreaRef}
defaultValue={value}
onChange={handleChange}
style={{ overflowY: "auto", resize: "none", height: "auto" }}
style={{ overflowY: "auto", height: "auto" }}
/>
<div className="absolute right-0 top-[-10px] py-2">
<Button
Expand Down Expand Up @@ -223,13 +223,45 @@ export function Message({

export function AddLLMChat({ onAdd }: { onAdd: (vendor: string) => void }) {
const [vendor, setVendor] = useState("");
const [busy, setBusy] = useState(false);
const [vendorKey, setVendorKey] = useState<string>("");

useEffect(() => {
if (typeof window === "undefined") return;
const keys = LLM_VENDORS.map((vendor) => {
const keyName = LLM_VENDOR_APIS.find(
(api) => api.label.toUpperCase() === vendor.value.toUpperCase()
);
if (!keyName) return null;
const key = window.localStorage.getItem(keyName.value.toUpperCase());
if (!key) return null;
return { value: keyName.value.toUpperCase(), label: vendor.label, key };
});
const venKey = keys.find((key) => key?.label.toLowerCase() === vendor);
setVendorKey(venKey?.key || "");
}, [busy, vendor]);

return (
<div className="w-[450px] h-[600px] rounded-lg border border-dashed border-muted-foreground flex items-center justify-center gap-1">
<LLMPicker setVendor={setVendor} />
<Button size={"sm"} onClick={() => onAdd(vendor)}>
Add
<PlusIcon className="ml-2 h-4 w-4" />
</Button>
<div className="w-[450px] h-[600px] rounded-lg border border-dashed border-muted-foreground flex flex-col items-center justify-center gap-4">
<div className="flex items-center gap-2">
<LLMPicker setVendor={setVendor} />
<Button
size={"sm"}
onClick={() => onAdd(vendor)}
disabled={vendorKey === "" || vendor === "" || busy}
>
Add
<PlusIcon className="ml-2 h-4 w-4" />
</Button>
</div>
{vendorKey === "" && (
<span className="text-sm font-semibold w-72">
Please add your {vendor} API key in the{" "}
<Link href="/settings/keys" className="underline text-blue-400">
settings page.
</Link>
</span>
)}
</div>
);
}
36 changes: 36 additions & 0 deletions components/playground/import-messages.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { cn } from "@/lib/utils";
import { DotsHorizontalIcon } from "@radix-ui/react-icons";
import { Button } from "../ui/button";
import ImportPrompt from "./import-prompt";
import ImportTraceConversation from "./import-trace-conversation";

export default function ImportMessages({
setMessages,
className = "",
}: {
setMessages: any;
className?: string;
}) {
return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button
variant="outline"
size={"icon"}
className={cn(className, "bg-muted")}
>
<DotsHorizontalIcon />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="w-full flex flex-col gap-1">
<ImportTraceConversation setMessages={setMessages} />
<ImportPrompt setMessages={setMessages} />
</DropdownMenuContent>
</DropdownMenu>
);
}
Loading

0 comments on commit a8678f6

Please sign in to comment.