rm system message

This commit is contained in:
Andrew Pareles 2025-01-22 22:37:40 -08:00
parent 0919775e77
commit b3ebe85c04
5 changed files with 57 additions and 50 deletions

View file

@ -98,24 +98,10 @@ export class LLMMessageService extends Disposable implements ILLMMessageService
}
const { providerName, modelName } = modelSelection
// end early if there are no messages
if (proxyParams.messages.length === 0) {
onError({ message: 'Please send a message first.', fullError: null })
return null
}
// make first message contain system message for compatibility
// this is needed because o1 and other models do not accept a system prompt
// add ai instructions here because we don't have access to voidSettingsService on the other side of the proxy
const aiInstructions = this.voidSettingsService.state.globalSettings.aiInstructions
const systemMessageIdx = proxyParams.messages.findIndex(m => m.role === 'system')
const systemMessage = systemMessageIdx > -1 ? proxyParams.messages[systemMessageIdx].content : undefined
proxyParams.messages[0].content = ``
+ (systemMessage ? `\n\n${systemMessage}` : '')
+ (aiInstructions ? `\n\n${aiInstructions}` : '')
+ `\n\nHere are the user's instructions:\n\n${proxyParams.messages[0].content}`
if (systemMessageIdx > -1) { // remove role='system' messages
proxyParams.messages.splice(systemMessageIdx, 1)
}
if (aiInstructions)
proxyParams.messages.unshift({ role: 'system', content: aiInstructions })
// add state for request id
const requestId_ = generateUuid();

View file

@ -30,6 +30,12 @@ export type LLMMessage = {
content: string;
}
export type _InternalLLMMessage = {
role: 'user' | 'assistant';
content: string;
}
export type ServiceSendLLMFeatureParams = {
useProviderFor: 'Ctrl+K';
range: IRange;
@ -80,7 +86,7 @@ export type EventLLMMessageOnFinalMessageParams = Parameters<OnFinalMessage>[0]
export type EventLLMMessageOnErrorParams = Parameters<OnError>[0] & { requestId: string }
export type _InternalSendLLMMessageFnType = (params: {
messages: LLMMessage[];
messages: _InternalLLMMessage[];
onText: OnText;
onFinalMessage: OnFinalMessage;
onError: OnError;

View file

@ -7,11 +7,6 @@ import Anthropic from '@anthropic-ai/sdk';
import { _InternalSendLLMMessageFnType } from '../../common/llmMessageTypes.js';
import { anthropicMaxPossibleTokens } from '../../common/voidSettingsTypes.js';
// Anthropic
type LLMMessageAnthropic = {
role: 'user' | 'assistant';
content: string;
}
export const sendAnthropicMsg: _InternalSendLLMMessageFnType = ({ messages, onText, onFinalMessage, onError, settingsOfProvider, modelName, _setAborter }) => {
const thisConfig = settingsOfProvider.anthropic
@ -24,20 +19,9 @@ export const sendAnthropicMsg: _InternalSendLLMMessageFnType = ({ messages, onTe
const anthropic = new Anthropic({ apiKey: thisConfig.apiKey, dangerouslyAllowBrowser: true });
// find system messages and concatenate them
const systemMessage = messages
.filter(msg => msg.role === 'system')
.map(msg => msg.content)
.join('\n');
// remove system messages for Anthropic
const anthropicMessages = messages.filter(msg => msg.role !== 'system') as LLMMessageAnthropic[]
const stream = anthropic.messages.stream({
system: systemMessage,
messages: anthropicMessages,
// system: systemMessage,
messages: messages,
model: modelName,
max_tokens: maxTokens,
});

View file

@ -16,22 +16,17 @@ export const sendGeminiMsg: _InternalSendLLMMessageFnType = async ({ messages, o
const genAI = new GoogleGenerativeAI(thisConfig.apiKey);
const model = genAI.getGenerativeModel({ model: modelName });
// remove system messages that get sent to Gemini
// str of all system messages
const systemMessage = messages
.filter(msg => msg.role === 'system')
.map(msg => msg.content)
.join('\n');
// Convert messages to Gemini format
const geminiMessages: Content[] = messages
.filter(msg => msg.role !== 'system')
.map((msg, i) => ({
parts: [{ text: msg.content }],
role: msg.role === 'assistant' ? 'model' : 'user'
}))
model.generateContentStream({ contents: geminiMessages, systemInstruction: systemMessage, })
model.generateContentStream({
// systemInstruction: systemMessage,
contents: geminiMessages,
})
.then(async response => {
_setAborter(() => response.stream.return(fullText))

View file

@ -3,7 +3,7 @@
* Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information.
*--------------------------------------------------------------------------------------*/
import { LLMMMessageParams, OnText, OnFinalMessage, OnError } from '../../common/llmMessageTypes.js';
import { LLMMMessageParams, OnText, OnFinalMessage, OnError, LLMMessage, _InternalLLMMessage } from '../../common/llmMessageTypes.js';
import { IMetricsService } from '../../common/metricsService.js';
import { sendAnthropicMsg } from './anthropic.js';
@ -12,8 +12,43 @@ import { sendOpenAIMsg } from './openai.js';
import { sendGeminiMsg } from './gemini.js';
import { sendGroqMsg } from './groq.js';
const cleanMessages = (messages: LLMMessage[]): _InternalLLMMessage[] => {
// trim message content (Anthropic and other providers give an error if there is trailing whitespace)
messages = messages.map(m => ({ ...m, content: m.content.trim() }))
// find system messages and concatenate them
const systemMessage = messages
.filter(msg => msg.role === 'system')
.map(msg => msg.content)
.join('\n') || undefined;
// remove all system messages
const noSystemMessages = messages
.filter(msg => msg.role !== 'system') as _InternalLLMMessage[]
// add system mesasges to first message (should be a user message)
if (systemMessage && (noSystemMessages.length !== 0)) {
const newFirstMessage = {
role: noSystemMessages[0].role,
content: (''
+ '<SYSTEM_MESSAGE>\n'
+ systemMessage
+ '\n'
+ '</SYSTEM_MESSAGE>\n'
+ noSystemMessages[0].content
)
}
noSystemMessages.splice(0, 1) // delete first message
noSystemMessages.unshift(newFirstMessage) // add new first message
}
return noSystemMessages
}
export const sendLLMMessage = ({
messages,
messages: messages_,
onText: onText_,
onFinalMessage: onFinalMessage_,
onError: onError_,
@ -26,9 +61,7 @@ export const sendLLMMessage = ({
metricsService: IMetricsService
) => {
// trim message content (Anthropic and other providers give an error if there is trailing whitespace)
messages = messages.map(m => ({ ...m, content: m.content.trim() }))
const messages = cleanMessages(messages_)
// only captures number of messages and message "shape", no actual code, instructions, prompts, etc
const captureChatEvent = (eventId: string, extras?: object) => {
@ -37,6 +70,9 @@ export const sendLLMMessage = ({
modelName,
numMessages: messages?.length,
messagesShape: messages?.map(msg => ({ role: msg.role, length: msg.content.length })),
origNumMessages: messages_?.length,
origMessagesShape: messages_?.map(msg => ({ role: msg.role, length: msg.content.length })),
...extras,
})
}