Refactor to use newver v4 version of Vercel AI package

This commit is contained in:
eduardruzga
2024-12-09 17:26:33 +02:00
parent 6e61a4fb95
commit fcb61ba499
9 changed files with 441 additions and 608 deletions

View File

@@ -8,17 +8,15 @@ export async function action(args: ActionFunctionArgs) {
return chatAction(args);
}
function parseCookies(cookieHeader: string) {
const cookies: any = {};
function parseCookies(cookieHeader: string): Record<string, string> {
const cookies: Record<string, string> = {};
// Split the cookie string by semicolons and spaces
const items = cookieHeader.split(';').map((cookie) => cookie.trim());
items.forEach((item) => {
const [name, ...rest] = item.split('=');
if (name && rest) {
// Decode the name and value, and join value parts in case it contains '='
const decodedName = decodeURIComponent(name.trim());
const decodedValue = decodeURIComponent(rest.join('=').trim());
cookies[decodedName] = decodedValue;
@@ -35,16 +33,15 @@ async function chatAction({ context, request }: ActionFunctionArgs) {
}>();
const cookieHeader = request.headers.get('Cookie');
// Parse the cookie's value (returns an object or null if no cookie exists)
const apiKeys = JSON.parse(parseCookies(cookieHeader || '').apiKeys || '{}');
const stream = new SwitchableStream();
try {
const options: StreamingOptions = {
toolChoice: 'none',
onFinish: async ({ text: content, finishReason }) => {
onFinish: async ({ text: content, finishReason, usage }) => {
console.log('usage', usage);
if (finishReason !== 'length') {
return stream.close();
}
@@ -62,13 +59,12 @@ async function chatAction({ context, request }: ActionFunctionArgs) {
const result = await streamText(messages, context.cloudflare.env, options, apiKeys);
return stream.switchSource(result.toAIStream());
return stream.switchSource(result.toDataStream());
},
};
const result = await streamText(messages, context.cloudflare.env, options, apiKeys);
stream.switchSource(result.toAIStream());
stream.switchSource(result.toDataStream());
return new Response(stream.readable, {
status: 200,
@@ -77,7 +73,7 @@ async function chatAction({ context, request }: ActionFunctionArgs) {
},
});
} catch (error: any) {
console.log(error);
console.error(error);
if (error.message?.includes('API key')) {
throw new Response('Invalid or missing API key', {

View File

@@ -1,5 +1,6 @@
import { type ActionFunctionArgs } from '@remix-run/cloudflare';
import { StreamingTextResponse, parseStreamPart } from 'ai';
//import { StreamingTextResponse, parseStreamPart } from 'ai';
import { streamText } from '~/lib/.server/llm/stream-text';
import { stripIndents } from '~/utils/stripIndent';
import type { ProviderInfo } from '~/types/model';
@@ -45,32 +46,32 @@ async function enhancerAction({ context, request }: ActionFunctionArgs) {
`[Model: ${model}]\n\n[Provider: ${providerName}]\n\n` +
stripIndents`
You are a professional prompt engineer specializing in crafting precise, effective prompts.
Your task is to enhance prompts by making them more specific, actionable, and effective.
Your task is to enhance prompts by making them more specific, actionable, and effective.
I want you to improve the user prompt that is wrapped in \`<original_prompt>\` tags.
I want you to improve the user prompt that is wrapped in \`<original_prompt>\` tags.
For valid prompts:
- Make instructions explicit and unambiguous
- Add relevant context and constraints
- Remove redundant information
- Maintain the core intent
- Ensure the prompt is self-contained
- Use professional language
For valid prompts:
- Make instructions explicit and unambiguous
- Add relevant context and constraints
- Remove redundant information
- Maintain the core intent
- Ensure the prompt is self-contained
- Use professional language
For invalid or unclear prompts:
- Respond with a clear, professional guidance message
- Keep responses concise and actionable
- Maintain a helpful, constructive tone
- Focus on what the user should provide
- Use a standard template for consistency
For invalid or unclear prompts:
- Respond with clear, professional guidance
- Keep responses concise and actionable
- Maintain a helpful, constructive tone
- Focus on what the user should provide
- Use a standard template for consistency
IMPORTANT: Your response must ONLY contain the enhanced prompt text.
Do not include any explanations, metadata, or wrapper tags.
IMPORTANT: Your response must ONLY contain the enhanced prompt text.
Do not include any explanations, metadata, or wrapper tags.
<original_prompt>
${message}
</original_prompt>
`,
<original_prompt>
${message}
</original_prompt>
`,
},
],
context.cloudflare.env,
@@ -85,7 +86,7 @@ async function enhancerAction({ context, request }: ActionFunctionArgs) {
for (const line of lines) {
try {
const parsed = parseStreamPart(line);
const parsed = JSON.parse(line);
if (parsed.type === 'text') {
controller.enqueue(encoder.encode(parsed.value));
@@ -100,7 +101,12 @@ async function enhancerAction({ context, request }: ActionFunctionArgs) {
const transformedStream = result.toDataStream().pipeThrough(transformStream);
return new StreamingTextResponse(transformedStream);
return new Response(transformedStream, {
status: 200,
headers: {
'Content-Type': 'text/plain; charset=utf-8',
},
});
} catch (error: unknown) {
console.log(error);