|
1 |
| -import OpenAI from "openai"; |
2 |
| -import { OpenAIStream, StreamingTextResponse } from "ai"; |
3 |
| -import { kv } from "@vercel/kv"; |
4 |
| -import { Ratelimit } from "@upstash/ratelimit"; |
5 |
| -import { match } from "ts-pattern"; |
6 |
| -import type { ChatCompletionMessageParam } from "openai/resources/index.mjs"; |
| 1 | +import OpenAI from 'openai'; |
| 2 | +import { OpenAIStream, StreamingTextResponse } from 'ai'; |
| 3 | +import { kv } from '@vercel/kv'; |
| 4 | +import { Ratelimit } from '@upstash/ratelimit'; |
| 5 | +import { match } from 'ts-pattern'; |
| 6 | +import type { ChatCompletionMessageParam } from 'openai/resources/index.mjs'; |
7 | 7 |
|
8 | 8 | // Create an OpenAI API client (that's edge friendly!)
|
9 | 9 | // Using LLamma's OpenAI client:
|
10 | 10 |
|
11 | 11 | // IMPORTANT! Set the runtime to edge: https://vercel.com/docs/functions/edge-functions/edge-runtime
|
12 |
| -export const runtime = "edge"; |
| 12 | +export const runtime = 'edge'; |
13 | 13 |
|
14 | 14 | const llama = new OpenAI({
|
15 |
| - apiKey: "ollama", |
16 |
| - baseURL: "http://localhost:11434/v1", |
| 15 | + apiKey: 'ollama', |
| 16 | + baseURL: 'http://localhost:11434/v1', |
17 | 17 | });
|
18 | 18 |
|
19 | 19 | export async function POST(req: Request): Promise<Response> {
|
20 | 20 | const openai = new OpenAI({
|
21 | 21 | apiKey: process.env.OPENAI_API_KEY,
|
22 |
| - baseURL: process.env.OPENAI_BASE_URL || "https://api.openai.com/v1", |
| 22 | + baseURL: process.env.OPENAI_BASE_URL || 'https://api.openai.com/v1', |
23 | 23 | });
|
24 | 24 | // Check if the OPENAI_API_KEY is set, if not return 400
|
25 |
| - if (!process.env.OPENAI_API_KEY || process.env.OPENAI_API_KEY === "") { |
26 |
| - return new Response( |
27 |
| - "Missing OPENAI_API_KEY - make sure to add it to your .env file.", |
28 |
| - { |
29 |
| - status: 400, |
30 |
| - }, |
31 |
| - ); |
| 25 | + if (!process.env.OPENAI_API_KEY || process.env.OPENAI_API_KEY === '') { |
| 26 | + return new Response('Missing OPENAI_API_KEY - make sure to add it to your .env file.', { |
| 27 | + status: 400, |
| 28 | + }); |
32 | 29 | }
|
33 | 30 | if (process.env.KV_REST_API_URL && process.env.KV_REST_API_TOKEN) {
|
34 |
| - const ip = req.headers.get("x-forwarded-for"); |
| 31 | + const ip = req.headers.get('x-forwarded-for'); |
35 | 32 | const ratelimit = new Ratelimit({
|
36 | 33 | redis: kv,
|
37 |
| - limiter: Ratelimit.slidingWindow(50, "1 d"), |
| 34 | + limiter: Ratelimit.slidingWindow(50, '1 d'), |
38 | 35 | });
|
39 | 36 |
|
40 |
| - const { success, limit, reset, remaining } = await ratelimit.limit( |
41 |
| - `novel_ratelimit_${ip}`, |
42 |
| - ); |
| 37 | + const { success, limit, reset, remaining } = await ratelimit.limit(`novel_ratelimit_${ip}`); |
43 | 38 |
|
44 | 39 | if (!success) {
|
45 |
| - return new Response("You have reached your request limit for the day.", { |
| 40 | + return new Response('You have reached your request limit for the day.', { |
46 | 41 | status: 429,
|
47 | 42 | headers: {
|
48 |
| - "X-RateLimit-Limit": limit.toString(), |
49 |
| - "X-RateLimit-Remaining": remaining.toString(), |
50 |
| - "X-RateLimit-Reset": reset.toString(), |
| 43 | + 'X-RateLimit-Limit': limit.toString(), |
| 44 | + 'X-RateLimit-Remaining': remaining.toString(), |
| 45 | + 'X-RateLimit-Reset': reset.toString(), |
51 | 46 | },
|
52 | 47 | });
|
53 | 48 | }
|
54 | 49 | }
|
55 | 50 |
|
56 | 51 | const { prompt, option, command } = await req.json();
|
57 | 52 | const messages = match(option)
|
58 |
| - .with("continue", () => [ |
| 53 | + .with('continue', () => [ |
59 | 54 | {
|
60 |
| - role: "system", |
| 55 | + role: 'system', |
61 | 56 | content:
|
62 |
| - "You are an AI writing assistant that continues existing text based on context from prior text. " + |
63 |
| - "Give more weight/priority to the later characters than the beginning ones. " + |
64 |
| - "Limit your response to no more than 200 characters, but make sure to construct complete sentences." + |
65 |
| - "Use Markdown formatting when appropriate.", |
| 57 | + 'You are an AI writing assistant that continues existing text based on context from prior text. ' + |
| 58 | + 'Give more weight/priority to the later characters than the beginning ones. ' + |
| 59 | + 'Limit your response to no more than 200 characters, but make sure to construct complete sentences.' + |
| 60 | + 'Use Markdown formatting when appropriate.', |
66 | 61 | },
|
67 | 62 | {
|
68 |
| - role: "user", |
| 63 | + role: 'user', |
69 | 64 | content: prompt,
|
70 | 65 | },
|
71 | 66 | ])
|
72 |
| - .with("improve", () => [ |
| 67 | + .with('improve', () => [ |
73 | 68 | {
|
74 |
| - role: "system", |
| 69 | + role: 'system', |
75 | 70 | content:
|
76 |
| - "You are an AI writing assistant that improves existing text. " + |
77 |
| - "Limit your response to no more than 200 characters, but make sure to construct complete sentences." + |
78 |
| - "Use Markdown formatting when appropriate.", |
| 71 | + 'You are an AI writing assistant that improves existing text. ' + |
| 72 | + 'Limit your response to no more than 200 characters, but make sure to construct complete sentences.' + |
| 73 | + 'Use Markdown formatting when appropriate.', |
79 | 74 | },
|
80 | 75 | {
|
81 |
| - role: "user", |
| 76 | + role: 'user', |
82 | 77 | content: `The existing text is: ${prompt}`,
|
83 | 78 | },
|
84 | 79 | ])
|
85 |
| - .with("shorter", () => [ |
| 80 | + .with('shorter', () => [ |
86 | 81 | {
|
87 |
| - role: "system", |
| 82 | + role: 'system', |
88 | 83 | content:
|
89 |
| - "You are an AI writing assistant that shortens existing text. " + |
90 |
| - "Use Markdown formatting when appropriate.", |
| 84 | + 'You are an AI writing assistant that shortens existing text. ' + 'Use Markdown formatting when appropriate.', |
91 | 85 | },
|
92 | 86 | {
|
93 |
| - role: "user", |
| 87 | + role: 'user', |
94 | 88 | content: `The existing text is: ${prompt}`,
|
95 | 89 | },
|
96 | 90 | ])
|
97 |
| - .with("longer", () => [ |
| 91 | + .with('longer', () => [ |
98 | 92 | {
|
99 |
| - role: "system", |
| 93 | + role: 'system', |
100 | 94 | content:
|
101 |
| - "You are an AI writing assistant that lengthens existing text. " + |
102 |
| - "Use Markdown formatting when appropriate.", |
| 95 | + 'You are an AI writing assistant that lengthens existing text. ' + |
| 96 | + 'Use Markdown formatting when appropriate.', |
103 | 97 | },
|
104 | 98 | {
|
105 |
| - role: "user", |
| 99 | + role: 'user', |
106 | 100 | content: `The existing text is: ${prompt}`,
|
107 | 101 | },
|
108 | 102 | ])
|
109 |
| - .with("fix", () => [ |
| 103 | + .with('fix', () => [ |
110 | 104 | {
|
111 |
| - role: "system", |
| 105 | + role: 'system', |
112 | 106 | content:
|
113 |
| - "You are an AI writing assistant that fixes grammar and spelling errors in existing text. " + |
114 |
| - "Limit your response to no more than 200 characters, but make sure to construct complete sentences." + |
115 |
| - "Use Markdown formatting when appropriate.", |
| 107 | + 'You are an AI writing assistant that fixes grammar and spelling errors in existing text. ' + |
| 108 | + 'Limit your response to no more than 200 characters, but make sure to construct complete sentences.' + |
| 109 | + 'Use Markdown formatting when appropriate.', |
116 | 110 | },
|
117 | 111 | {
|
118 |
| - role: "user", |
| 112 | + role: 'user', |
119 | 113 | content: `The existing text is: ${prompt}`,
|
120 | 114 | },
|
121 | 115 | ])
|
122 |
| - .with("zap", () => [ |
| 116 | + .with('zap', () => [ |
123 | 117 | {
|
124 |
| - role: "system", |
| 118 | + role: 'system', |
125 | 119 | content:
|
126 |
| - "You area an AI writing assistant that generates text based on a prompt. " + |
127 |
| - "You take an input from the user and a command for manipulating the text" + |
128 |
| - "Use Markdown formatting when appropriate.", |
| 120 | + 'You area an AI writing assistant that generates text based on a prompt. ' + |
| 121 | + 'You take an input from the user and a command for manipulating the text' + |
| 122 | + 'Use Markdown formatting when appropriate.', |
129 | 123 | },
|
130 | 124 | {
|
131 |
| - role: "user", |
| 125 | + role: 'user', |
132 | 126 | content: `For this text: ${prompt}. You have to respect the command: ${command}`,
|
133 | 127 | },
|
134 | 128 | ])
|
135 | 129 | .run() as ChatCompletionMessageParam[];
|
136 | 130 |
|
137 | 131 | const response = await openai.chat.completions.create({
|
138 |
| - model: "gpt-3.5-turbo", |
| 132 | + model: 'gpt-3.5-turbo', |
139 | 133 | stream: true,
|
140 | 134 | messages,
|
141 | 135 | temperature: 0.7,
|
|
0 commit comments