From 3328af06a059325549ed8c22cd553693960b8b82 Mon Sep 17 00:00:00 2001 From: Simon Farshid Date: Tue, 6 Aug 2024 18:55:25 -0700 Subject: [PATCH] feat: ask-docs (#653) --- apps/docs/app/api/entelligence/route.ts | 25 ++++++ apps/docs/app/docs/layout.tsx | 8 +- apps/docs/components/docs-chat/DocsChat.tsx | 86 +++++++++++++++++++++ 3 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 apps/docs/app/api/entelligence/route.ts create mode 100644 apps/docs/components/docs-chat/DocsChat.tsx diff --git a/apps/docs/app/api/entelligence/route.ts b/apps/docs/app/api/entelligence/route.ts new file mode 100644 index 000000000..abf3135e0 --- /dev/null +++ b/apps/docs/app/api/entelligence/route.ts @@ -0,0 +1,25 @@ +export const POST = async (req: Request) => { + const { messages } = (await req.json()) as { + messages: { role: "user" | "assistant"; content: string }[]; + }; + + // remove the most recent user question + const { content: question, role } = messages.pop()!; + if (role !== "user" || !question) throw new Error("No question provided"); + + return fetch(process.env["ENTELLIGENCE_API_URL"]!, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + history: messages.map((m) => ({ + role: m.role, + content: m.content, + })), + question, + vectorDBUrl: "Yonom&assistant-ui", + advancedAgent: false, + }), + }); +}; diff --git a/apps/docs/app/docs/layout.tsx b/apps/docs/app/docs/layout.tsx index cbaf6d4ab..5627e25c5 100644 --- a/apps/docs/app/docs/layout.tsx +++ b/apps/docs/app/docs/layout.tsx @@ -2,7 +2,13 @@ import { DocsLayout } from "fumadocs-ui/layout"; import type { ReactNode } from "react"; import { docsOptions } from "./layout.config"; import "fumadocs-ui/twoslash.css"; +import { DocsChat } from "@/components/docs-chat/DocsChat"; export default function Layout({ children }: { children: ReactNode }) { - return {children}; + return ( + + {children} + + + ); } diff --git a/apps/docs/components/docs-chat/DocsChat.tsx b/apps/docs/components/docs-chat/DocsChat.tsx new file mode 100644 index 000000000..0bed76cdc --- /dev/null +++ b/apps/docs/components/docs-chat/DocsChat.tsx @@ -0,0 +1,86 @@ +"use client"; + +import { + AssistantModal, + ChatModelAdapter, + useLocalRuntime, +} from "@assistant-ui/react"; +import { makeMarkdownText } from "@assistant-ui/react-markdown"; +import { makePrismAsyncSyntaxHighlighter } from "@assistant-ui/react-syntax-highlighter"; +import { coldarkDark } from "react-syntax-highlighter/dist/esm/styles/prism"; +import remarkGfm from "remark-gfm"; + +co asAsyncIterable(source: ReadableStream): AsyncIterable { + return { + [Symbol.asyncIterator]: () => { + const reader = source.getReader(); + return { + async next(): Promise> { + const { done, value } = await reader.read(); + return done + ? { done: true, value: undefined } + : { done: false, value }; + }, + }; + }, + }; +} + +const MyCustomAdapter: ChatModelAdapter = { + async *run({ messages, abortSignal }) { + const messagesToSend = messages.map((m) => ({ + role: m.role, + content: m.content + .filter((c) => c.type === "text") + .map((c) => c.text) + .join(" "), + })); + + const response = await fetch("/api/entelligence", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + messages: messagesToSend, + }), + signal: abortSignal, + }); + + let text = ""; + for await (const chunk of asAsyncIterable( + response.body!.pipeThrough(new TextDecoderStream()), + )) { + text += chunk; + yield { content: [{ type: "text", text }] }; + } + }, +}; + +const SyntaxHighlighter = makePrismAsyncSyntaxHighlighter({ + style: coldarkDark, + customStyle: { + margin: 0, + backgroundColor: "black", + }, +}); +const MarkdownText = makeMarkdownText({ + remarkPlugins: [remarkGfm], + components: { + SyntaxHighlighter, + }, +}); + +export const DocsChat = () => { + const runtime = useLocalRuntime(MyCustomAdapter); + + return ( + + ); +};