-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
19 changed files
with
771 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import type { Config } from "drizzle-kit"; | ||
import { env } from "./src/lib/env.mjs"; | ||
|
||
export default { | ||
schema: "./lib/db/schema", | ||
dialect: "postgresql", | ||
out: "./lib/db/migrations", | ||
dbCredentials: { | ||
url: env.DATABASE_URL, | ||
}, | ||
} satisfies Config; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
export const VercelIcon = ({ size = 17 }) => { | ||
return ( | ||
<svg | ||
height={size} | ||
strokeLinejoin="round" | ||
viewBox="0 0 16 16" | ||
width={size} | ||
style={{ color: "currentcolor" }} | ||
> | ||
<path | ||
fillRule="evenodd" | ||
clipRule="evenodd" | ||
d="M8 1L16 15H0L8 1Z" | ||
fill="currentColor" | ||
></path> | ||
</svg> | ||
); | ||
}; | ||
|
||
export const InformationIcon = ({ size = 17 }) => { | ||
return ( | ||
<svg | ||
height={size} | ||
strokeLinejoin="round" | ||
viewBox="0 0 16 16" | ||
width={size} | ||
style={{ color: "currentcolor" }} | ||
> | ||
<path | ||
fillRule="evenodd" | ||
clipRule="evenodd" | ||
d="M8 14.5C11.5899 14.5 14.5 11.5899 14.5 8C14.5 4.41015 11.5899 1.5 8 1.5C4.41015 1.5 1.5 4.41015 1.5 8C1.5 11.5899 4.41015 14.5 8 14.5ZM8 16C12.4183 16 16 12.4183 16 8C16 3.58172 12.4183 0 8 0C3.58172 0 0 3.58172 0 8C0 12.4183 3.58172 16 8 16ZM6.25 7H7H7.74999C8.30227 7 8.74999 7.44772 8.74999 8V11.5V12.25H7.24999V11.5V8.5H7H6.25V7ZM8 6C8.55229 6 9 5.55228 9 5C9 4.44772 8.55229 4 8 4C7.44772 4 7 4.44772 7 5C7 5.55228 7.44772 6 8 6Z" | ||
fill="currentColor" | ||
></path> | ||
</svg> | ||
); | ||
}; | ||
|
||
export const LoadingIcon = () => { | ||
return ( | ||
<svg | ||
height="16" | ||
strokeLinejoin="round" | ||
viewBox="0 0 16 16" | ||
width="16" | ||
style={{ color: "currentcolor" }} | ||
> | ||
<g clipPath="url(#clip0_2393_1490)"> | ||
<path d="M8 0V4" stroke="currentColor" strokeWidth="1.5"></path> | ||
<path | ||
opacity="0.5" | ||
d="M8 16V12" | ||
stroke="currentColor" | ||
strokeWidth="1.5" | ||
></path> | ||
<path | ||
opacity="0.9" | ||
d="M3.29773 1.52783L5.64887 4.7639" | ||
stroke="currentColor" | ||
strokeWidth="1.5" | ||
></path> | ||
<path | ||
opacity="0.1" | ||
d="M12.7023 1.52783L10.3511 4.7639" | ||
stroke="currentColor" | ||
strokeWidth="1.5" | ||
></path> | ||
<path | ||
opacity="0.4" | ||
d="M12.7023 14.472L10.3511 11.236" | ||
stroke="currentColor" | ||
strokeWidth="1.5" | ||
></path> | ||
<path | ||
opacity="0.6" | ||
d="M3.29773 14.472L5.64887 11.236" | ||
stroke="currentColor" | ||
strokeWidth="1.5" | ||
></path> | ||
<path | ||
opacity="0.2" | ||
d="M15.6085 5.52783L11.8043 6.7639" | ||
stroke="currentColor" | ||
strokeWidth="1.5" | ||
></path> | ||
<path | ||
opacity="0.7" | ||
d="M0.391602 10.472L4.19583 9.23598" | ||
stroke="currentColor" | ||
strokeWidth="1.5" | ||
></path> | ||
<path | ||
opacity="0.3" | ||
d="M15.6085 10.4722L11.8043 9.2361" | ||
stroke="currentColor" | ||
strokeWidth="1.5" | ||
></path> | ||
<path | ||
opacity="0.8" | ||
d="M0.391602 5.52783L4.19583 6.7639" | ||
stroke="currentColor" | ||
strokeWidth="1.5" | ||
></path> | ||
</g> | ||
<defs> | ||
<clipPath id="clip0_2393_1490"> | ||
<rect width="16" height="16" fill="white"></rect> | ||
</clipPath> | ||
</defs> | ||
</svg> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import * as React from "react"; | ||
|
||
const buttonVariants = { | ||
default: "btn btn-primary", | ||
destructive: "btn btn-error", | ||
outline: "btn btn-outline", | ||
secondary: "btn btn-secondary", | ||
ghost: "btn btn-ghost", | ||
link: "btn btn-link", | ||
}; | ||
|
||
const sizeVariants = { | ||
default: "btn-md", | ||
sm: "btn-sm", | ||
lg: "btn-lg", | ||
icon: "btn-square btn-md", | ||
}; | ||
|
||
export interface ButtonProps | ||
extends React.ButtonHTMLAttributes<HTMLButtonElement> { | ||
variant?: keyof typeof buttonVariants; | ||
size?: keyof typeof sizeVariants; | ||
} | ||
|
||
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>( | ||
({ className, variant = "default", size = "default", ...props }, ref) => { | ||
return ( | ||
<button | ||
className={`btn ${buttonVariants[variant]} ${sizeVariants[size]} ${className || ""}`} | ||
ref={ref} | ||
{...props} | ||
/> | ||
); | ||
}, | ||
); | ||
Button.displayName = "Button"; | ||
|
||
export { Button, buttonVariants }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import * as React from "react"; | ||
|
||
import { cn } from "@/lib/utils"; | ||
|
||
export interface InputProps | ||
extends React.InputHTMLAttributes<HTMLInputElement> {} | ||
|
||
const Input = React.forwardRef<HTMLInputElement, InputProps>( | ||
({ className, type, ...props }, ref) => { | ||
return ( | ||
<input | ||
type={type} | ||
className={cn( | ||
"flex h-10 w-full rounded-md bg-background px-3 py-2 text-sm file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground outline-none disabled:cursor-not-allowed disabled:opacity-50", | ||
className, | ||
)} | ||
ref={ref} | ||
{...props} | ||
/> | ||
); | ||
}, | ||
); | ||
Input.displayName = "Input"; | ||
|
||
export { Input }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import React from "react"; | ||
|
||
const Label = React.forwardRef< | ||
HTMLLabelElement, | ||
React.LabelHTMLAttributes<HTMLLabelElement> | ||
>(({ className, ...props }, ref) => ( | ||
<label | ||
ref={ref} | ||
className={`text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70 ${className}`} | ||
{...props} | ||
/> | ||
)); | ||
|
||
Label.displayName = "Label"; | ||
|
||
export { Label }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
import { createResource } from "@/lib/actions/resources"; | ||
import { findRelevantContent } from "@/lib/ai/embeddings"; | ||
import { openai } from "@ai-sdk/openai"; | ||
import { convertToCoreMessages, generateObject, streamText, tool } from "ai"; | ||
import { z } from "zod"; | ||
|
||
// Allow streaming responses up to 30 seconds | ||
export const maxDuration = 30; | ||
|
||
export async function POST(req: Request) { | ||
const { messages } = await req.json(); | ||
|
||
const result = await streamText({ | ||
model: openai("gpt-4o"), | ||
messages: convertToCoreMessages(messages), | ||
system: `You are a helpful assistant acting as the users' second brain. | ||
Use tools on every request. | ||
Be sure to getInformation from your knowledge base before answering any questions. | ||
If the user presents infromation about themselves, use the addResource tool to store it. | ||
If a response requires multiple tools, call one tool after another without responding to the user. | ||
If a response requires information from an additional tool to generate a response, call the appropriate tools in order before responding to the user. | ||
ONLY respond to questions using information from tool calls. | ||
if no relevant information is found in the tool calls, respond, "Sorry, I don't know." | ||
Be sure to adhere to any instructions in tool calls ie. if they say to responsd like "...", do exactly that. | ||
If the relevant information is not a direct match to the users prompt, you can be creative in deducing the answer. | ||
Keep responses short and concise. Answer in a single sentence where possible. | ||
If you are unsure, use the getInformation tool and you can use common sense to reason based on the information you do have. | ||
Use your abilities as a reasoning machine to answer questions based on the information you do have. | ||
`, | ||
tools: { | ||
addResource: tool({ | ||
description: `add a resource to your knowledge base. | ||
If the user provides a random piece of knowledge unprompted, use this tool without asking for confirmation.`, | ||
parameters: z.object({ | ||
content: z | ||
.string() | ||
.describe("the content or resource to add to the knowledge base"), | ||
}), | ||
execute: async ({ content }) => createResource({ content }), | ||
}), | ||
getInformation: tool({ | ||
description: `get information from your knowledge base to answer questions.`, | ||
parameters: z.object({ | ||
question: z.string().describe("the users question"), | ||
similarQuestions: z.array(z.string()).describe("keywords to search"), | ||
}), | ||
execute: async ({ similarQuestions }) => { | ||
const results = await Promise.all( | ||
similarQuestions.map( | ||
async (question) => await findRelevantContent(question), | ||
), | ||
); | ||
// Flatten the array of arrays and remove duplicates based on 'name' | ||
const uniqueResults = Array.from( | ||
new Map(results.flat().map((item) => [item?.name, item])).values(), | ||
); | ||
return uniqueResults; | ||
}, | ||
}), | ||
understandQuery: tool({ | ||
description: `understand the users query. use this tool on every prompt.`, | ||
parameters: z.object({ | ||
query: z.string().describe("the users query"), | ||
toolsToCallInOrder: z | ||
.array(z.string()) | ||
.describe( | ||
"these are the tools you need to call in the order necessary to respond to the users query", | ||
), | ||
}), | ||
execute: async ({ query }) => { | ||
const { object } = await generateObject({ | ||
model: openai("gpt-4o"), | ||
system: | ||
"You are a query understanding assistant. Analyze the user query and generate similar questions.", | ||
schema: z.object({ | ||
questions: z | ||
.array(z.string()) | ||
.max(3) | ||
.describe("similar questions to the user's query. be concise."), | ||
}), | ||
prompt: `Analyze this query: "${query}". Provide the following: | ||
3 similar questions that could help answer the user's query`, | ||
}); | ||
return object.questions; | ||
}, | ||
}), | ||
}, | ||
}); | ||
|
||
return result.toDataStreamResponse(); | ||
} |
Empty file.
Oops, something went wrong.