Moved provider and setProvider variables to the higher level component so that it can be accessed in sendMessage.
Browse files
app/components/chat/BaseChat.tsx
CHANGED
@@ -24,8 +24,7 @@ const EXAMPLE_PROMPTS = [
|
|
24 |
|
25 |
const providerList = [...new Set(MODEL_LIST.map((model) => model.provider))]
|
26 |
|
27 |
-
const ModelSelector = ({ model, setModel, modelList, providerList }) => {
|
28 |
-
const [provider, setProvider] = useState(DEFAULT_PROVIDER);
|
29 |
return (
|
30 |
<div className="mb-2">
|
31 |
<select
|
@@ -79,6 +78,8 @@ interface BaseChatProps {
|
|
79 |
input?: string;
|
80 |
model: string;
|
81 |
setModel: (model: string) => void;
|
|
|
|
|
82 |
handleStop?: () => void;
|
83 |
sendMessage?: (event: React.UIEvent, messageInput?: string) => void;
|
84 |
handleInputChange?: (event: React.ChangeEvent<HTMLTextAreaElement>) => void;
|
@@ -100,6 +101,8 @@ export const BaseChat = React.forwardRef<HTMLDivElement, BaseChatProps>(
|
|
100 |
input = '',
|
101 |
model,
|
102 |
setModel,
|
|
|
|
|
103 |
sendMessage,
|
104 |
handleInputChange,
|
105 |
enhancePrompt,
|
@@ -157,6 +160,8 @@ export const BaseChat = React.forwardRef<HTMLDivElement, BaseChatProps>(
|
|
157 |
model={model}
|
158 |
setModel={setModel}
|
159 |
modelList={MODEL_LIST}
|
|
|
|
|
160 |
providerList={providerList}
|
161 |
/>
|
162 |
<div
|
|
|
24 |
|
25 |
const providerList = [...new Set(MODEL_LIST.map((model) => model.provider))]
|
26 |
|
27 |
+
const ModelSelector = ({ model, setModel, provider, setProvider, modelList, providerList }) => {
|
|
|
28 |
return (
|
29 |
<div className="mb-2">
|
30 |
<select
|
|
|
78 |
input?: string;
|
79 |
model: string;
|
80 |
setModel: (model: string) => void;
|
81 |
+
provider: string;
|
82 |
+
setProvider: (provider: string) => void;
|
83 |
handleStop?: () => void;
|
84 |
sendMessage?: (event: React.UIEvent, messageInput?: string) => void;
|
85 |
handleInputChange?: (event: React.ChangeEvent<HTMLTextAreaElement>) => void;
|
|
|
101 |
input = '',
|
102 |
model,
|
103 |
setModel,
|
104 |
+
provider,
|
105 |
+
setProvider,
|
106 |
sendMessage,
|
107 |
handleInputChange,
|
108 |
enhancePrompt,
|
|
|
160 |
model={model}
|
161 |
setModel={setModel}
|
162 |
modelList={MODEL_LIST}
|
163 |
+
provider={provider}
|
164 |
+
setProvider={setProvider}
|
165 |
providerList={providerList}
|
166 |
/>
|
167 |
<div
|
app/components/chat/Chat.client.tsx
CHANGED
@@ -11,7 +11,7 @@ import { useChatHistory } from '~/lib/persistence';
|
|
11 |
import { chatStore } from '~/lib/stores/chat';
|
12 |
import { workbenchStore } from '~/lib/stores/workbench';
|
13 |
import { fileModificationsToHTML } from '~/utils/diff';
|
14 |
-
import { DEFAULT_MODEL } from '~/utils/constants';
|
15 |
import { cubicEasingFn } from '~/utils/easings';
|
16 |
import { createScopedLogger, renderLogger } from '~/utils/logger';
|
17 |
import { BaseChat } from './BaseChat';
|
@@ -74,6 +74,7 @@ export const ChatImpl = memo(({ initialMessages, storeMessageHistory }: ChatProp
|
|
74 |
|
75 |
const [chatStarted, setChatStarted] = useState(initialMessages.length > 0);
|
76 |
const [model, setModel] = useState(DEFAULT_MODEL);
|
|
|
77 |
|
78 |
const { showChat } = useStore(chatStore);
|
79 |
|
@@ -182,7 +183,7 @@ export const ChatImpl = memo(({ initialMessages, storeMessageHistory }: ChatProp
|
|
182 |
* manually reset the input and we'd have to manually pass in file attachments. However, those
|
183 |
* aren't relevant here.
|
184 |
*/
|
185 |
-
append({ role: 'user', content: `[Model: ${model}]\n\n${diff}\n\n${_input}` });
|
186 |
|
187 |
/**
|
188 |
* After sending a new message we reset all modifications since the model
|
@@ -190,7 +191,7 @@ export const ChatImpl = memo(({ initialMessages, storeMessageHistory }: ChatProp
|
|
190 |
*/
|
191 |
workbenchStore.resetAllFileModifications();
|
192 |
} else {
|
193 |
-
append({ role: 'user', content: `[Model: ${model}]\n\n${_input}` });
|
194 |
}
|
195 |
|
196 |
setInput('');
|
@@ -215,6 +216,8 @@ export const ChatImpl = memo(({ initialMessages, storeMessageHistory }: ChatProp
|
|
215 |
sendMessage={sendMessage}
|
216 |
model={model}
|
217 |
setModel={setModel}
|
|
|
|
|
218 |
messageRef={messageRef}
|
219 |
scrollRef={scrollRef}
|
220 |
handleInputChange={handleInputChange}
|
|
|
11 |
import { chatStore } from '~/lib/stores/chat';
|
12 |
import { workbenchStore } from '~/lib/stores/workbench';
|
13 |
import { fileModificationsToHTML } from '~/utils/diff';
|
14 |
+
import { DEFAULT_MODEL, DEFAULT_PROVIDER } from '~/utils/constants';
|
15 |
import { cubicEasingFn } from '~/utils/easings';
|
16 |
import { createScopedLogger, renderLogger } from '~/utils/logger';
|
17 |
import { BaseChat } from './BaseChat';
|
|
|
74 |
|
75 |
const [chatStarted, setChatStarted] = useState(initialMessages.length > 0);
|
76 |
const [model, setModel] = useState(DEFAULT_MODEL);
|
77 |
+
const [provider, setProvider] = useState(DEFAULT_PROVIDER);
|
78 |
|
79 |
const { showChat } = useStore(chatStore);
|
80 |
|
|
|
183 |
* manually reset the input and we'd have to manually pass in file attachments. However, those
|
184 |
* aren't relevant here.
|
185 |
*/
|
186 |
+
append({ role: 'user', content: `[Model: ${model}]\n\n[Provider: ${provider}]\n\n${diff}\n\n${_input}` });
|
187 |
|
188 |
/**
|
189 |
* After sending a new message we reset all modifications since the model
|
|
|
191 |
*/
|
192 |
workbenchStore.resetAllFileModifications();
|
193 |
} else {
|
194 |
+
append({ role: 'user', content: `[Model: ${model}]\n\n[Provider: ${provider}]\n\n${_input}` });
|
195 |
}
|
196 |
|
197 |
setInput('');
|
|
|
216 |
sendMessage={sendMessage}
|
217 |
model={model}
|
218 |
setModel={setModel}
|
219 |
+
provider={provider}
|
220 |
+
setProvider={setProvider}
|
221 |
messageRef={messageRef}
|
222 |
scrollRef={scrollRef}
|
223 |
handleInputChange={handleInputChange}
|
app/lib/.server/llm/stream-text.ts
CHANGED
@@ -24,42 +24,51 @@ export type Messages = Message[];
|
|
24 |
|
25 |
export type StreamingOptions = Omit<Parameters<typeof _streamText>[0], 'model'>;
|
26 |
|
27 |
-
function
|
28 |
const modelRegex = /^\[Model: (.*?)\]\n\n/;
|
29 |
-
const
|
30 |
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
return { model, content };
|
35 |
-
}
|
36 |
|
37 |
-
//
|
38 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
39 |
}
|
40 |
|
41 |
export function streamText(messages: Messages, env: Env, options?: StreamingOptions) {
|
42 |
let currentModel = DEFAULT_MODEL;
|
|
|
|
|
43 |
const processedMessages = messages.map((message) => {
|
44 |
if (message.role === 'user') {
|
45 |
-
const { model, content } =
|
46 |
-
|
47 |
-
|
|
|
48 |
}
|
|
|
|
|
|
|
49 |
return { ...message, content };
|
50 |
}
|
51 |
-
return message;
|
52 |
-
});
|
53 |
|
54 |
-
|
|
|
55 |
|
56 |
return _streamText({
|
57 |
-
model: getModel(
|
58 |
system: getSystemPrompt(),
|
59 |
maxTokens: MAX_TOKENS,
|
60 |
-
// headers: {
|
61 |
-
// 'anthropic-beta': 'max-tokens-3-5-sonnet-2024-07-15',
|
62 |
-
// },
|
63 |
messages: convertToCoreMessages(processedMessages),
|
64 |
...options,
|
65 |
});
|
|
|
24 |
|
25 |
export type StreamingOptions = Omit<Parameters<typeof _streamText>[0], 'model'>;
|
26 |
|
27 |
+
function extractPropertiesFromMessage(message: Message): { model: string; provider: string; content: string } {
|
28 |
const modelRegex = /^\[Model: (.*?)\]\n\n/;
|
29 |
+
const providerRegex = /\[Provider: (.*?)\]\n\n/;
|
30 |
|
31 |
+
// Extract model
|
32 |
+
const modelMatch = message.content.match(modelRegex);
|
33 |
+
const model = modelMatch ? modelMatch[1] : DEFAULT_MODEL;
|
|
|
|
|
34 |
|
35 |
+
// Extract provider
|
36 |
+
const providerMatch = message.content.match(providerRegex);
|
37 |
+
const provider = providerMatch ? providerMatch[1] : DEFAULT_PROVIDER;
|
38 |
+
|
39 |
+
// Remove model and provider lines from content
|
40 |
+
const cleanedContent = message.content
|
41 |
+
.replace(modelRegex, '')
|
42 |
+
.replace(providerRegex, '')
|
43 |
+
.trim();
|
44 |
+
|
45 |
+
return { model, provider, content: cleanedContent };
|
46 |
}
|
47 |
|
48 |
export function streamText(messages: Messages, env: Env, options?: StreamingOptions) {
|
49 |
let currentModel = DEFAULT_MODEL;
|
50 |
+
let currentProvider = DEFAULT_PROVIDER;
|
51 |
+
|
52 |
const processedMessages = messages.map((message) => {
|
53 |
if (message.role === 'user') {
|
54 |
+
const { model, provider, content } = extractPropertiesFromMessage(message);
|
55 |
+
|
56 |
+
if (MODEL_LIST.find((m) => m.name === model)) {
|
57 |
+
currentModel = model;
|
58 |
}
|
59 |
+
|
60 |
+
currentProvider = provider;
|
61 |
+
|
62 |
return { ...message, content };
|
63 |
}
|
|
|
|
|
64 |
|
65 |
+
return message; // No changes for non-user messages
|
66 |
+
});
|
67 |
|
68 |
return _streamText({
|
69 |
+
model: getModel(currentProvider, currentModel, env),
|
70 |
system: getSystemPrompt(),
|
71 |
maxTokens: MAX_TOKENS,
|
|
|
|
|
|
|
72 |
messages: convertToCoreMessages(processedMessages),
|
73 |
...options,
|
74 |
});
|