Skip to content

Commit a28c2b5

Browse files
committed
Fix up clean up
1 parent 0a0237b commit a28c2b5

File tree

4 files changed

+151
-6
lines changed

4 files changed

+151
-6
lines changed

src/app/api/chat/route.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,10 @@ export async function POST(req: Request) {
3535

3636
(context as PineconeRecord[]).forEach(match => {
3737
const source = (match.metadata as Metadata).source
38+
39+
console.log(`source: %o`, source)
3840
// Ensure source is a blog url, meaning it contains the path src/app/blog
39-
if (!source.includes('src/app/blog')) return
41+
if (!source.includes('src/content/blog')) return
4042
blogUrls.add((match.metadata as Metadata).source);
4143
docs.push((match.metadata as Metadata).text);
4244
});

src/app/chat-demo/page.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
'use client'
2+
3+
import ChatPageClientDemo from '../chat/ChatPageClientDemo';
4+
5+
export default function ChatDemoPage() {
6+
return <ChatPageClientDemo />;
7+
}

src/app/chat/ChatPageClient.tsx

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -265,11 +265,9 @@ export default function ChatPageClient() {
265265
<div className="mt-8">
266266
<h3 className="mb-4 text-xl font-semibold">Related Posts</h3>
267267
<div className="space-y-4">
268-
{(articles as BlogWithSlug[]).map((article) => {
269-
// Temporary fix: Prepend `/blog/` to the slug if it's missing
270-
const correctedSlug = article.slug.startsWith('blog/') ? article.slug : `blog/${article.slug}`;
271-
return <ContentCard key={article.slug} article={{ ...article, slug: correctedSlug }} />;
272-
})}
268+
{(articles as BlogWithSlug[]).map((article) => (
269+
<ContentCard key={article.slug} article={article} />
270+
))}
273271
</div>
274272
</div>
275273
)}
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
'use client'
2+
3+
import React, { useState, useEffect, Suspense } from 'react';
4+
import { Container } from '@/components/Container';
5+
import { useChat } from 'ai/react';
6+
import { clsx } from 'clsx';
7+
import RandomPortrait from '@/components/RandomPortrait';
8+
import SearchForm from '@/components/SearchForm';
9+
import { LoadingAnimation } from '@/components/LoadingAnimation';
10+
import { ContentCard } from '@/components/ContentCard';
11+
import { BlogWithSlug } from '@/types';
12+
13+
const prepopulatedQuestions = [
14+
"What is the programming bug?",
15+
"Why do you love Next.js so much?",
16+
"What do you do at Pinecone?",
17+
"How can I become a better developer?",
18+
"What is ggshield and why is it important?",
19+
"How can I use AI to complete side projects more quickly?"
20+
];
21+
22+
export default function ChatPageClientDemo() {
23+
const [isLoading, setIsLoading] = useState(false);
24+
const [articles, setArticles] = useState<BlogWithSlug[]>([]);
25+
const [isClient, setIsClient] = useState(false);
26+
27+
const { messages, input, setInput, handleSubmit, reload: resetChat } = useChat({
28+
onResponse(response) {
29+
const sourcesHeader = response.headers.get('x-sources');
30+
const parsedArticles: BlogWithSlug[] = sourcesHeader
31+
? (JSON.parse(atob(sourcesHeader as string)) as BlogWithSlug[])
32+
: [];
33+
setArticles(parsedArticles);
34+
setIsLoading(false);
35+
},
36+
headers: {},
37+
onFinish() {},
38+
onError() {
39+
setIsLoading(false);
40+
}
41+
});
42+
43+
const handleSearch = async (query: string) => {
44+
setInput(query);
45+
const customSubmitEvent = {
46+
preventDefault: () => { },
47+
} as unknown as React.FormEvent<HTMLFormElement>;
48+
await handleSubmit(customSubmitEvent);
49+
};
50+
51+
const clearChatState = () => {
52+
resetChat();
53+
setArticles([]);
54+
setInput("");
55+
const currentMessages = messages.length;
56+
setTimeout(() => {
57+
if (messages.length === currentMessages) {
58+
resetChat();
59+
}
60+
}, 100);
61+
};
62+
63+
useEffect(() => {
64+
setIsClient(true);
65+
}, []);
66+
67+
return (
68+
<Container>
69+
<div className="max-w-7xl mx-auto mt-16 sm:mt-32">
70+
<div className="flex flex-col md:flex-row items-start mb-12">
71+
<div className="flex-1 pl-8">
72+
<h1 className="text-4xl font-bold tracking-tight text-zinc-800 dark:text-zinc-100 sm:text-5xl mb-6">
73+
Internal RAG Chatbot Demo
74+
</h1>
75+
<p className="text-base text-zinc-600 dark:text-zinc-400 mb-6">
76+
This is a demonstration of a Retrieval-Augmented Generation (RAG) chatbot. Enter your question below to see how it responds using internal documentation.
77+
</p>
78+
</div>
79+
<div className="mt-6 md:mt-0 w-full md:w-80 h-80">
80+
<Suspense fallback={<div className="w-full h-full bg-gray-200 rounded-lg pr-8 mr-8"></div>}>
81+
<RandomPortrait width={300} height={300} />
82+
</Suspense>
83+
</div>
84+
</div>
85+
86+
{/* Chat interface */}
87+
<div className="mb-8">
88+
<SearchForm
89+
suggestedSearches={prepopulatedQuestions}
90+
onSearch={handleSearch}
91+
setIsLoading={setIsLoading}
92+
buttonText="Ask question"
93+
onClearChat={clearChatState}
94+
showClearButton={messages.length > 0}
95+
/>
96+
</div>
97+
98+
{isLoading && messages?.length > 0 && <LoadingAnimation />}
99+
100+
{/* Chat messages and related posts */}
101+
<div className="flex flex-col md:flex-row">
102+
<div className="flex-1 pr-0 md:pr-6 mb-6 md:mb-0">
103+
{messages.map((m) => (
104+
<div
105+
key={m.id}
106+
className="mb-4 whitespace-pre-wrap text-lg leading-relaxed"
107+
>
108+
<span
109+
className={clsx('font-bold', {
110+
'text-blue-700': m.role === 'user',
111+
'text-green-700': m.role !== 'user',
112+
})}
113+
>
114+
{m.role === 'user'
115+
? 'You: '
116+
: "Chatbot: "}
117+
</span>
118+
{m.content}
119+
</div>
120+
))}
121+
</div>
122+
<div className="md:w-1/3">
123+
{Array.isArray(articles) && (articles.length > 0) && (
124+
<div className="mt-8">
125+
<h3 className="mb-4 text-xl font-semibold">Related Posts</h3>
126+
<div className="space-y-4">
127+
{(articles as BlogWithSlug[]).map((article) => (
128+
<ContentCard key={article.slug} article={article} />
129+
))}
130+
</div>
131+
</div>
132+
)}
133+
</div>
134+
</div>
135+
</div>
136+
</Container>
137+
);
138+
}

0 commit comments

Comments
 (0)