Skip to content

Commit

Permalink
feat: added getting started page (openlit#73)
Browse files Browse the repository at this point in the history
  • Loading branch information
AmanAgarwal041 authored Feb 23, 2024
1 parent 254b218 commit cbe8e02
Show file tree
Hide file tree
Showing 9 changed files with 539 additions and 8 deletions.
259 changes: 258 additions & 1 deletion src/client/package-lock.json

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion src/client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,15 @@
"next": "14.0.4",
"next-auth": "^4.24.5",
"react": "^18",
"react-dom": "^18"
"react-dom": "^18",
"react-syntax-highlighter": "^15.5.0"
},
"devDependencies": {
"@types/lodash": "^4.14.202",
"@types/node": "^20",
"@types/react": "^18",
"@types/react-dom": "^18",
"@types/react-syntax-highlighter": "^15.5.11",
"autoprefixer": "^10.0.1",
"eslint": "^8",
"eslint-config-next": "14.0.4",
Expand Down
12 changes: 9 additions & 3 deletions src/client/src/app/(auth)/auth-form.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
"use client";
import { DEFAULT_LOGGED_IN_ROUTE } from "@/constants/route";
import asaw from "@/utils/asaw";
import { signIn } from "next-auth/react";
import Image from "next/image";
import Link from "next/link";
import { useSearchParams } from "next/navigation";
import { useState } from "react";

const errors = {
Expand All @@ -26,6 +29,9 @@ const SignInError = ({ error }: { error: keyof typeof errors }) => {
};

export function AuthForm({ type }: { type: "login" | "register" }) {
const searchParams = useSearchParams();
const callbackUrl: string =
(searchParams.get("callbackUrl") as string) || DEFAULT_LOGGED_IN_ROUTE;
const [error, setError] = useState<string>("");
async function authWrapper(fn: any) {
const [err, response] = await asaw(fn());
Expand All @@ -40,12 +46,12 @@ export function AuthForm({ type }: { type: "login" | "register" }) {
return;
}

window.location.replace("/dashboard");
window.location.replace(callbackUrl);
}
async function login(formData: FormData) {
authWrapper(() =>
signIn("login", {
callbackUrl: "/dashboard",
callbackUrl,
email: formData.get("email") as string,
password: formData.get("password") as string,
redirect: false,
Expand All @@ -56,7 +62,7 @@ export function AuthForm({ type }: { type: "login" | "register" }) {
async function register(formData: FormData) {
authWrapper(() =>
signIn("register", {
callbackUrl: "/dashboard",
callbackUrl,
email: formData.get("email") as string,
password: formData.get("password") as string,
redirect: false,
Expand Down
220 changes: 220 additions & 0 deletions src/client/src/app/(playground)/getting-started/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
"use client";

import CodeBlock from "@/components/common/code-block";
import { Tab } from "@headlessui/react";

export default function GettingStarted() {
const code = [
{
key: "python",
text: "Python",
component: (
<div className="flex flex-col border border-secondary text-sm rounded-b-lg p-3 text-tertiary">
<p>
Install the{" "}
<a
href="https://pypi.org/project/dokumetry/"
className="text-primary/[0.7] hover:text-primary bg-secondary px-1"
>
dokumetry
</a>{" "}
python sdk using pip:
</p>
<CodeBlock
className="text-xs"
code={`pip install dokumetry`}
language="bash"
/>
<p className="mt-2">
Add the following two lines to your application code:
</p>
<CodeBlock
className="text-xs"
code={`import dokumetry
dokumetry.init(llm=client, doku_url="YOUR_DOKU_URL", api_key="YOUR_DOKU_TOKEN")`}
language="python"
/>
<p className="mt-2">
Example Usage for monitoring{" "}
<a
className="text-primary/[0.7] hover:text-primary bg-secondary px-1"
href="https://platform.openai.com/docs/introduction"
>
OpenAI
</a>{" "}
Usage:
</p>
<CodeBlock
className="text-xs"
code={`from openai import OpenAI
import dokumetry
client = OpenAI(
api_key="YOUR_OPENAI_KEY"
)
# Pass the above \`client\` object along with your DOKU URL and API key and this will make sure that all OpenAI calls are automatically tracked.
dokumetry.init(llm=client, doku_url="YOUR_DOKU_URL", api_key="YOUR_DOKU_TOKEN")
chat_completion = client.chat.completions.create(
messages=[
{
"role": "user",
"content": "What is LLM Observability",
}
],
model="gpt-3.5-turbo",
)`}
language="python"
/>
<p className="mt-2">
Refer to the{" "}
<a
className="text-primary/[0.7] hover:text-primary bg-secondary px-1"
href="https://github.com/dokulabs/dokumetry-python"
>
dokumetry python sdk
</a>{" "}
repository for more advanced configurations and use cases.
</p>
</div>
),
},
{
key: "node",
text: "NodeJs",
component: (
<div className="flex flex-col border border-secondary text-sm rounded-b-lg p-3 text-tertiary">
<p>
Install the{" "}
<a
href="https://www.npmjs.com/package/dokumetry"
className="text-primary/[0.7] hover:text-primary bg-secondary px-1"
>
dokumetry
</a>{" "}
nodejs sdk using npm:
</p>
<CodeBlock
className="text-xs"
code={`npm install dokumetry`}
language="bash"
/>
<p className="mt-2">
Add the following two lines to your application code:
</p>
<CodeBlock
className="text-xs"
code={`import DokuMetry from "dokumetry";
DokuMetry.init({llm: openai, dokuUrl: "YOUR_DOKU_URL", apiKey: "YOUR_DOKU_TOKEN"});`}
language="javascript"
/>
<p className="mt-2">
Example Usage for monitoring{" "}
<a
className="text-primary/[0.7] hover:text-primary bg-secondary px-1"
href="https://platform.openai.com/docs/introduction"
>
OpenAI
</a>{" "}
Usage:
</p>
<CodeBlock
className="text-xs"
code={`import OpenAI from "openai";
import DokuMetry from "dokumetry";
const openai = new OpenAI({
apiKey: "My API Key", // defaults to process.env["OPENAI_API_KEY"]
});
// Pass the above \`openai\` object along with your DOKU URL and API key and this will make sure that all OpenAI calls are automatically tracked.
DokuMetry.init({llm: openai, dokuUrl: "YOUR_DOKU_URL", apiKey: "YOUR_DOKU_TOKEN"})
async function main() {
const chatCompletion = await openai.chat.completions.create({
messages: [{ role: "user", content: "What are the key to effective observability?" }],
model: "gpt-3.5-turbo",
});
}
main();`}
language="javascript"
/>
<p className="mt-2">
Refer to the{" "}
<a
className="text-primary/[0.7] hover:text-primary bg-secondary px-1"
href="https://github.com/dokulabs/dokumetry-node"
>
dokumetry nodejs sdk
</a>{" "}
repository for more advanced configurations and use cases.
</p>
</div>
),
},
];

return (
<div className="flex flex-col w-full flex-1 overflow-auto relative">
<p className="mb-5 text-sm font-medium border-l-4 border-primary p-3 text-primary bg-secondary/[0.5]">
Doku is an open-source observability tool engineered for Large Language
Models (LLMs). Designed for ease of integration into existing LLM
applications, Doku offers unparalleled insights into usage, performance,
and overhead—allowing you to analyze, optimize, and scale your AI
applications and LLM usage effectively.
</p>
<p className="mb-5 text-tertiary text-sm">
With the <span className="text-primary">dokumetry</span> SDKs for
<a
href="https://pypi.org/project/dokumetry/"
className="text-primary/[0.7] hover:text-primary bg-secondary px-1"
>
Python
</a>{" "}
and{" "}
<a
href="https://www.npmjs.com/package/dokumetry"
className="text-primary/[0.7] hover:text-primary bg-secondary px-1"
>
NodeJS
</a>{" "}
, sending observability data to Doku is just two lines of code in your
application. Once integrated, the SDKs take care of capturing and
conveying LLM usage data directly to your Doku instance, requiring
minimal effort on your part.
</p>
<div className="w-full">
<Tab.Group>
<Tab.List className="flex space-x-1 bg-white sticky top-0 z-20">
{code.map((item) => (
<Tab
key={item.key}
className={({ selected }) =>
`w-auto py-2 px-3 text-sm font-medium leading-5 outline-none border-b-2 ${
selected
? "text-primary border-primary"
: "text-tertiary/[0.3] border-white"
}`
}
>
{item.text}
</Tab>
))}
</Tab.List>
<Tab.Panels className="w-full mt-3">
{code.map((item, idx) => (
<Tab.Panel
key={idx}
className={`rounded-xl bg-white outline-none`}
>
{item.component}
</Tab.Panel>
))}
</Tab.Panels>
</Tab.Group>
</div>
</div>
);
}
8 changes: 7 additions & 1 deletion src/client/src/components/(playground)/sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import { signOut } from "next-auth/react";
import { ReactElement } from "react";
import {
AcademicCapIcon,
CircleStackIcon,
HomeModernIcon,
KeyIcon,
Expand All @@ -22,6 +23,11 @@ const ICON_CLASSES =
"flex-shrink-0 w-6 h-6 transition duration-75 transition duration-75";

const SIDEBAR_ITEMS: SidebarItemProps[] = [
{
icon: <AcademicCapIcon className={ICON_CLASSES} />,
text: "Getting started",
link: "/getting-started",
},
{
icon: <HomeModernIcon className={ICON_CLASSES} />,
text: "Dashboard",
Expand Down Expand Up @@ -97,7 +103,7 @@ export default function Sidebar() {
className={
item.link === pathname
? "border-r-4 border-primary text-primary bg-primary/[.09]"
: "text-tertiary"
: "text-tertiary/[0.9] hover:text-primary"
}
{...item}
/>
Expand Down
36 changes: 36 additions & 0 deletions src/client/src/components/common/code-block.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { DocumentDuplicateIcon } from "@heroicons/react/24/outline";
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
import { dracula } from "react-syntax-highlighter/dist/esm/styles/prism";
import copyToCB from "copy-to-clipboard";

export default function CodeBlock({
className = "",
code,
copy = true,
language,
}: {
className?: string;
code: string;
copy?: boolean;
language: string;
}) {
const onClickCopy = () => copyToCB(code);

return (
<section className="relative group">
<SyntaxHighlighter
language={language}
style={dracula}
className={`overflow-hidden ${className}`}
>
{code}
</SyntaxHighlighter>
{copy && (
<DocumentDuplicateIcon
className="w-4 h-4 absolute right-3 top-4 hidden group-hover:inline-block z-10 text-secondary hover:text-primary cursor-pointer"
onClick={onClickCopy}
/>
)}
</section>
);
}
1 change: 1 addition & 0 deletions src/client/src/constants/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const DEFAULT_LOGGED_IN_ROUTE = "/getting-started";
4 changes: 3 additions & 1 deletion src/client/src/middleware.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { getToken } from "next-auth/jwt";
import { withAuth } from "next-auth/middleware";
import { NextResponse } from "next/server";
import { DEFAULT_LOGGED_IN_ROUTE } from "@/constants/route";

export default withAuth(
async function middleware(req) {
Expand All @@ -20,7 +21,7 @@ export default withAuth(

if (isAuthPage) {
if (isAuth) {
return NextResponse.redirect(new URL("/dashboard", req.url));
return NextResponse.redirect(new URL(DEFAULT_LOGGED_IN_ROUTE, req.url));
}

return null;
Expand Down Expand Up @@ -60,6 +61,7 @@ export const config = {
"/api/:path*",
"/login",
"/register",
"/getting-started",
"/dashboard",
"/api-keys",
"/requests",
Expand Down
3 changes: 2 additions & 1 deletion src/client/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@
"@/lib/*": ["./src/lib/*"],
"@/components/*": ["./src/components/*"],
"@/prisma/*": ["./prisma/*"],
"@/utils/*": ["./src/utils/*"]
"@/utils/*": ["./src/utils/*"],
"@/constants/*": ["./src/constants/*"],
}
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
Expand Down

0 comments on commit cbe8e02

Please sign in to comment.