Sujal Shah
commited on
Commit
·
4ac0af4
1
Parent(s):
88700c2
fix: enhance prompt "Invalid or missing provider" bad request error
Browse files- app/lib/hooks/usePromptEnhancer.ts +19 -18
- app/routes/api.enhancer.ts +19 -14
app/lib/hooks/usePromptEnhancer.ts
CHANGED
@@ -1,4 +1,5 @@
|
|
1 |
import { useState } from 'react';
|
|
|
2 |
import { createScopedLogger } from '~/utils/logger';
|
3 |
|
4 |
const logger = createScopedLogger('usePromptEnhancement');
|
@@ -13,54 +14,54 @@ export function usePromptEnhancer() {
|
|
13 |
};
|
14 |
|
15 |
const enhancePrompt = async (
|
16 |
-
input: string,
|
17 |
setInput: (value: string) => void,
|
18 |
model: string,
|
19 |
-
provider:
|
20 |
-
apiKeys?: Record<string, string
|
21 |
) => {
|
22 |
setEnhancingPrompt(true);
|
23 |
setPromptEnhanced(false);
|
24 |
-
|
25 |
const requestBody: any = {
|
26 |
message: input,
|
27 |
model,
|
28 |
provider,
|
29 |
};
|
30 |
-
|
31 |
if (apiKeys) {
|
32 |
requestBody.apiKeys = apiKeys;
|
33 |
}
|
34 |
-
|
35 |
const response = await fetch('/api/enhancer', {
|
36 |
method: 'POST',
|
37 |
body: JSON.stringify(requestBody),
|
38 |
});
|
39 |
-
|
40 |
const reader = response.body?.getReader();
|
41 |
-
|
42 |
const originalInput = input;
|
43 |
-
|
44 |
if (reader) {
|
45 |
const decoder = new TextDecoder();
|
46 |
-
|
47 |
let _input = '';
|
48 |
let _error;
|
49 |
-
|
50 |
try {
|
51 |
setInput('');
|
52 |
-
|
53 |
while (true) {
|
54 |
const { value, done } = await reader.read();
|
55 |
-
|
56 |
if (done) {
|
57 |
break;
|
58 |
}
|
59 |
-
|
60 |
_input += decoder.decode(value);
|
61 |
-
|
62 |
logger.trace('Set input', _input);
|
63 |
-
|
64 |
setInput(_input);
|
65 |
}
|
66 |
} catch (error) {
|
@@ -70,10 +71,10 @@ export function usePromptEnhancer() {
|
|
70 |
if (_error) {
|
71 |
logger.error(_error);
|
72 |
}
|
73 |
-
|
74 |
setEnhancingPrompt(false);
|
75 |
setPromptEnhanced(true);
|
76 |
-
|
77 |
setTimeout(() => {
|
78 |
setInput(_input);
|
79 |
});
|
|
|
1 |
import { useState } from 'react';
|
2 |
+
import type { ProviderInfo } from '~/types/model';
|
3 |
import { createScopedLogger } from '~/utils/logger';
|
4 |
|
5 |
const logger = createScopedLogger('usePromptEnhancement');
|
|
|
14 |
};
|
15 |
|
16 |
const enhancePrompt = async (
|
17 |
+
input: string,
|
18 |
setInput: (value: string) => void,
|
19 |
model: string,
|
20 |
+
provider: ProviderInfo,
|
21 |
+
apiKeys?: Record<string, string>,
|
22 |
) => {
|
23 |
setEnhancingPrompt(true);
|
24 |
setPromptEnhanced(false);
|
25 |
+
|
26 |
const requestBody: any = {
|
27 |
message: input,
|
28 |
model,
|
29 |
provider,
|
30 |
};
|
31 |
+
|
32 |
if (apiKeys) {
|
33 |
requestBody.apiKeys = apiKeys;
|
34 |
}
|
35 |
+
|
36 |
const response = await fetch('/api/enhancer', {
|
37 |
method: 'POST',
|
38 |
body: JSON.stringify(requestBody),
|
39 |
});
|
40 |
+
|
41 |
const reader = response.body?.getReader();
|
42 |
+
|
43 |
const originalInput = input;
|
44 |
+
|
45 |
if (reader) {
|
46 |
const decoder = new TextDecoder();
|
47 |
+
|
48 |
let _input = '';
|
49 |
let _error;
|
50 |
+
|
51 |
try {
|
52 |
setInput('');
|
53 |
+
|
54 |
while (true) {
|
55 |
const { value, done } = await reader.read();
|
56 |
+
|
57 |
if (done) {
|
58 |
break;
|
59 |
}
|
60 |
+
|
61 |
_input += decoder.decode(value);
|
62 |
+
|
63 |
logger.trace('Set input', _input);
|
64 |
+
|
65 |
setInput(_input);
|
66 |
}
|
67 |
} catch (error) {
|
|
|
71 |
if (_error) {
|
72 |
logger.error(_error);
|
73 |
}
|
74 |
+
|
75 |
setEnhancingPrompt(false);
|
76 |
setPromptEnhanced(true);
|
77 |
+
|
78 |
setTimeout(() => {
|
79 |
setInput(_input);
|
80 |
});
|
app/routes/api.enhancer.ts
CHANGED
@@ -2,7 +2,7 @@ import { type ActionFunctionArgs } from '@remix-run/cloudflare';
|
|
2 |
import { StreamingTextResponse, parseStreamPart } from 'ai';
|
3 |
import { streamText } from '~/lib/.server/llm/stream-text';
|
4 |
import { stripIndents } from '~/utils/stripIndent';
|
5 |
-
import type {
|
6 |
|
7 |
const encoder = new TextEncoder();
|
8 |
const decoder = new TextDecoder();
|
@@ -12,25 +12,27 @@ export async function action(args: ActionFunctionArgs) {
|
|
12 |
}
|
13 |
|
14 |
async function enhancerAction({ context, request }: ActionFunctionArgs) {
|
15 |
-
const { message, model, provider, apiKeys } = await request.json<{
|
16 |
message: string;
|
17 |
model: string;
|
18 |
-
provider:
|
19 |
apiKeys?: Record<string, string>;
|
20 |
}>();
|
21 |
|
22 |
-
|
|
|
|
|
23 |
if (!model || typeof model !== 'string') {
|
24 |
throw new Response('Invalid or missing model', {
|
25 |
status: 400,
|
26 |
-
statusText: 'Bad Request'
|
27 |
});
|
28 |
}
|
29 |
|
30 |
-
if (!
|
31 |
throw new Response('Invalid or missing provider', {
|
32 |
status: 400,
|
33 |
-
statusText: 'Bad Request'
|
34 |
});
|
35 |
}
|
36 |
|
@@ -39,7 +41,9 @@ async function enhancerAction({ context, request }: ActionFunctionArgs) {
|
|
39 |
[
|
40 |
{
|
41 |
role: 'user',
|
42 |
-
content:
|
|
|
|
|
43 |
I want you to improve the user prompt that is wrapped in \`<original_prompt>\` tags.
|
44 |
|
45 |
IMPORTANT: Only respond with the improved prompt and nothing else!
|
@@ -52,23 +56,24 @@ async function enhancerAction({ context, request }: ActionFunctionArgs) {
|
|
52 |
],
|
53 |
context.cloudflare.env,
|
54 |
undefined,
|
55 |
-
apiKeys
|
56 |
);
|
57 |
|
58 |
const transformStream = new TransformStream({
|
59 |
transform(chunk, controller) {
|
60 |
const text = decoder.decode(chunk);
|
61 |
-
const lines = text.split('\n').filter(line => line.trim() !== '');
|
62 |
-
|
63 |
for (const line of lines) {
|
64 |
try {
|
65 |
const parsed = parseStreamPart(line);
|
|
|
66 |
if (parsed.type === 'text') {
|
67 |
controller.enqueue(encoder.encode(parsed.value));
|
68 |
}
|
69 |
} catch (e) {
|
70 |
-
//
|
71 |
-
console.warn('Failed to parse stream part:', line);
|
72 |
}
|
73 |
}
|
74 |
},
|
@@ -83,7 +88,7 @@ async function enhancerAction({ context, request }: ActionFunctionArgs) {
|
|
83 |
if (error instanceof Error && error.message?.includes('API key')) {
|
84 |
throw new Response('Invalid or missing API key', {
|
85 |
status: 401,
|
86 |
-
statusText: 'Unauthorized'
|
87 |
});
|
88 |
}
|
89 |
|
|
|
2 |
import { StreamingTextResponse, parseStreamPart } from 'ai';
|
3 |
import { streamText } from '~/lib/.server/llm/stream-text';
|
4 |
import { stripIndents } from '~/utils/stripIndent';
|
5 |
+
import type { ProviderInfo } from '~/types/model';
|
6 |
|
7 |
const encoder = new TextEncoder();
|
8 |
const decoder = new TextDecoder();
|
|
|
12 |
}
|
13 |
|
14 |
async function enhancerAction({ context, request }: ActionFunctionArgs) {
|
15 |
+
const { message, model, provider, apiKeys } = await request.json<{
|
16 |
message: string;
|
17 |
model: string;
|
18 |
+
provider: ProviderInfo;
|
19 |
apiKeys?: Record<string, string>;
|
20 |
}>();
|
21 |
|
22 |
+
const { name: providerName } = provider;
|
23 |
+
|
24 |
+
// validate 'model' and 'provider' fields
|
25 |
if (!model || typeof model !== 'string') {
|
26 |
throw new Response('Invalid or missing model', {
|
27 |
status: 400,
|
28 |
+
statusText: 'Bad Request',
|
29 |
});
|
30 |
}
|
31 |
|
32 |
+
if (!providerName || typeof providerName !== 'string') {
|
33 |
throw new Response('Invalid or missing provider', {
|
34 |
status: 400,
|
35 |
+
statusText: 'Bad Request',
|
36 |
});
|
37 |
}
|
38 |
|
|
|
41 |
[
|
42 |
{
|
43 |
role: 'user',
|
44 |
+
content:
|
45 |
+
`[Model: ${model}]\n\n[Provider: ${providerName}]\n\n` +
|
46 |
+
stripIndents`
|
47 |
I want you to improve the user prompt that is wrapped in \`<original_prompt>\` tags.
|
48 |
|
49 |
IMPORTANT: Only respond with the improved prompt and nothing else!
|
|
|
56 |
],
|
57 |
context.cloudflare.env,
|
58 |
undefined,
|
59 |
+
apiKeys,
|
60 |
);
|
61 |
|
62 |
const transformStream = new TransformStream({
|
63 |
transform(chunk, controller) {
|
64 |
const text = decoder.decode(chunk);
|
65 |
+
const lines = text.split('\n').filter((line) => line.trim() !== '');
|
66 |
+
|
67 |
for (const line of lines) {
|
68 |
try {
|
69 |
const parsed = parseStreamPart(line);
|
70 |
+
|
71 |
if (parsed.type === 'text') {
|
72 |
controller.enqueue(encoder.encode(parsed.value));
|
73 |
}
|
74 |
} catch (e) {
|
75 |
+
// skip invalid JSON lines
|
76 |
+
console.warn('Failed to parse stream part:', line, e);
|
77 |
}
|
78 |
}
|
79 |
},
|
|
|
88 |
if (error instanceof Error && error.message?.includes('API key')) {
|
89 |
throw new Response('Invalid or missing API key', {
|
90 |
status: 401,
|
91 |
+
statusText: 'Unauthorized',
|
92 |
});
|
93 |
}
|
94 |
|