Skip to content

Commit eb5e189

Browse files
committed
bring your own ai key
1 parent 0de9dde commit eb5e189

File tree

2 files changed

+44
-24
lines changed

2 files changed

+44
-24
lines changed

apps/web/src/app/api/chat/route.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
import { anthropic } from '@ai-sdk/anthropic';
1+
import { createAnthropic } from '@ai-sdk/anthropic';
22
import { streamText, tool } from 'ai';
33
import { getInstalledDataSources } from '@/lib/tinybird';
44
import { z } from 'zod';
55

66
// Allow streaming responses up to 30 seconds
77
export const maxDuration = 30;
8+
const apiKey = process.env.ANTHROPIC_API_KEY;
89

910
const event_type_context = `
1011
tool,event_type,description
@@ -103,11 +104,16 @@ auth0,w,"A warning has happened during a login flow"
103104

104105
export async function POST(req: Request) {
105106
const token = req.headers.get('token') ?? '';
107+
const userAIApiKey = req.headers.get('ai_key') ?? '';
106108
const { messages } = await req.json();
107109
console.log('token: ' + token)
108110

111+
const anthropic = createAnthropic(
112+
{ apiKey: apiKey ?? userAIApiKey },
113+
);
114+
109115
const result = streamText({
110-
model: anthropic('claude-3-5-sonnet-latest'),
116+
model: anthropic.languageModel('claude-3-5-sonnet-20240620'),
111117
maxSteps: 5,
112118
tools: {
113119
getAvailableDataSources: tool({

apps/web/src/app/chat/page.tsx

Lines changed: 36 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,31 +7,45 @@ import { Suspense } from 'react';
77
function ChatContent() {
88
const { messages, input, handleInputChange, handleSubmit } = useChat();
99
const [token] = useQueryState('token');
10-
11-
return (
12-
<div className="flex flex-col w-full max-w-md py-24 mx-auto stretch">
13-
{messages.map(m => (
14-
<div key={m.id} className="whitespace-pre-wrap">
15-
{m.role === 'user' ? 'User: ' : 'AI: '}
16-
{m.toolInvocations ? (
17-
<pre>{JSON.stringify(m.toolInvocations, null, 2)}</pre>
18-
) : (
19-
<p>{m.content}</p>
20-
)}
21-
</div>
22-
))}
10+
const [aiKey, setAiKey] = useQueryState('ai_key');
2311

24-
<form onSubmit={(e) => {
25-
handleSubmit(e, { headers: { token: token ?? '' } });
26-
}}>
12+
return (
13+
<>
14+
<div className="fixed top-0 w-full max-w-md p-4 bg-white">
15+
<span className="inline-block w-24">Token:</span>
2716
<input
28-
className="fixed bottom-0 w-full max-w-md p-2 mb-8 border border-gray-300 rounded shadow-xl"
29-
value={input}
30-
placeholder="Say something..."
31-
onChange={handleInputChange}
17+
type="password"
18+
className="inline-block w-full p-2 border border-gray-300 rounded"
19+
value={aiKey || ''}
20+
onChange={(e) => setAiKey(e.target.value)}
21+
placeholder="Enter your OpenAI/Anthropic API key..."
3222
/>
33-
</form>
34-
</div>
23+
</div>
24+
25+
<div className="flex flex-col w-full max-w-md py-24 mx-auto stretch">
26+
{messages.map(m => (
27+
<div key={m.id} className="whitespace-pre-wrap">
28+
{m.role === 'user' ? 'User: ' : 'AI: '}
29+
{m.toolInvocations ? (
30+
<pre>{JSON.stringify(m.toolInvocations, null, 2)}</pre>
31+
) : (
32+
<p>{m.content}</p>
33+
)}
34+
</div>
35+
))}
36+
37+
<form onSubmit={(e) => {
38+
handleSubmit(e, { headers: { token: token ?? '', ai_key: aiKey ?? '' } });
39+
}}>
40+
<input
41+
className="fixed bottom-0 w-full max-w-md p-2 mb-8 border border-gray-300 rounded shadow-xl"
42+
value={input}
43+
placeholder="Say something..."
44+
onChange={handleInputChange}
45+
/>
46+
</form>
47+
</div>
48+
</>
3549
);
3650
}
3751

0 commit comments

Comments
 (0)