fix stuff
This commit is contained in:
+14
-10
@@ -709,16 +709,10 @@ export function createRepositories(db, config) {
|
|||||||
chat.scenario_prompt ?? null,
|
chat.scenario_prompt ?? null,
|
||||||
chat.scenario_summary ?? null
|
chat.scenario_summary ?? null
|
||||||
).lastInsertRowid;
|
).lastInsertRowid;
|
||||||
if (chat.context_summary) {
|
const importedMessageIds = new Map();
|
||||||
statements.updateChatContextSummary.run(
|
|
||||||
chat.context_summary,
|
|
||||||
Number(chat.context_summary_message_id || 0),
|
|
||||||
chatId,
|
|
||||||
username
|
|
||||||
);
|
|
||||||
}
|
|
||||||
for (const message of chat.messages || []) {
|
for (const message of chat.messages || []) {
|
||||||
statements.insertChatMessage.run(
|
const mappedRetryPromptId = importedMessageIds.get(message.retryPromptMessageId) ?? null;
|
||||||
|
const result = statements.insertChatMessage.run(
|
||||||
chatId,
|
chatId,
|
||||||
message.role,
|
message.role,
|
||||||
message.content,
|
message.content,
|
||||||
@@ -726,7 +720,17 @@ export function createRepositories(db, config) {
|
|||||||
JSON.stringify(message.retryVariants || [message.content || ""]),
|
JSON.stringify(message.retryVariants || [message.content || ""]),
|
||||||
Number(message.retryActiveIndex || 0),
|
Number(message.retryActiveIndex || 0),
|
||||||
Number(message.retryRetriesUsed || 0),
|
Number(message.retryRetriesUsed || 0),
|
||||||
message.retryPromptMessageId ?? null
|
mappedRetryPromptId
|
||||||
|
);
|
||||||
|
if (message.sourceId != null) importedMessageIds.set(message.sourceId, Number(result.lastInsertRowid));
|
||||||
|
}
|
||||||
|
if (chat.context_summary) {
|
||||||
|
const mappedSummaryMessageId = importedMessageIds.get(Number(chat.context_summary_message_id || 0)) || 0;
|
||||||
|
statements.updateChatContextSummary.run(
|
||||||
|
chat.context_summary,
|
||||||
|
mappedSummaryMessageId,
|
||||||
|
chatId,
|
||||||
|
username
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
for (const memory of chat.memories || []) {
|
for (const memory of chat.memories || []) {
|
||||||
|
|||||||
+14
-2
@@ -154,9 +154,13 @@ export function createChatsRouter({repositories, chatService, modelService, conf
|
|||||||
|
|
||||||
if (existingMessage.role === "bot") {
|
if (existingMessage.role === "bot") {
|
||||||
const retryVariants = [...existingMessage.retryVariants];
|
const retryVariants = [...existingMessage.retryVariants];
|
||||||
const activeIndex = Number.isInteger(Number(req.validatedBody.retryActiveIndex))
|
const requestedIndex = Number(req.validatedBody.retryActiveIndex);
|
||||||
|
const activeIndex = Number.isInteger(requestedIndex)
|
||||||
? Number(req.validatedBody.retryActiveIndex)
|
? Number(req.validatedBody.retryActiveIndex)
|
||||||
: existingMessage.retryActiveIndex;
|
: existingMessage.retryActiveIndex;
|
||||||
|
if (activeIndex < 0 || activeIndex >= retryVariants.length) {
|
||||||
|
return res.status(400).json({error: "retryActiveIndex is out of range"});
|
||||||
|
}
|
||||||
retryVariants[activeIndex] = req.validatedBody.content;
|
retryVariants[activeIndex] = req.validatedBody.content;
|
||||||
chatService.persistChatMessageRetryState({
|
chatService.persistChatMessageRetryState({
|
||||||
chatId,
|
chatId,
|
||||||
@@ -186,9 +190,13 @@ export function createChatsRouter({repositories, chatService, modelService, conf
|
|||||||
|
|
||||||
if (existingMessage.role === "bot") {
|
if (existingMessage.role === "bot") {
|
||||||
const retryVariants = [...existingMessage.retryVariants];
|
const retryVariants = [...existingMessage.retryVariants];
|
||||||
const activeIndex = Number.isInteger(Number(req.validatedBody.retryActiveIndex))
|
const requestedIndex = Number(req.validatedBody.retryActiveIndex);
|
||||||
|
const activeIndex = Number.isInteger(requestedIndex)
|
||||||
? Number(req.validatedBody.retryActiveIndex)
|
? Number(req.validatedBody.retryActiveIndex)
|
||||||
: existingMessage.retryActiveIndex;
|
: existingMessage.retryActiveIndex;
|
||||||
|
if (activeIndex < 0 || activeIndex >= retryVariants.length) {
|
||||||
|
return res.status(400).json({error: "retryActiveIndex is out of range"});
|
||||||
|
}
|
||||||
retryVariants[activeIndex] = req.validatedBody.content;
|
retryVariants[activeIndex] = req.validatedBody.content;
|
||||||
chatService.persistChatMessageRetryState({
|
chatService.persistChatMessageRetryState({
|
||||||
chatId,
|
chatId,
|
||||||
@@ -338,6 +346,8 @@ export function createChatsRouter({repositories, chatService, modelService, conf
|
|||||||
router.post("/chats/:id/messages/:messageId/retry", ...chatRateLimiters, async (req, res) => {
|
router.post("/chats/:id/messages/:messageId/retry", ...chatRateLimiters, async (req, res) => {
|
||||||
const chatId = Number(req.params.id);
|
const chatId = Number(req.params.id);
|
||||||
const messageId = Number(req.params.messageId);
|
const messageId = Number(req.params.messageId);
|
||||||
|
const chat = repositories.getChat(chatId, req.session.user);
|
||||||
|
if (!chat) return res.status(404).json({error: "Chat not found"});
|
||||||
const targetMessage = repositories.getChatMessage(chatId, messageId);
|
const targetMessage = repositories.getChatMessage(chatId, messageId);
|
||||||
if (!targetMessage) return res.status(404).json({error: "Message not found"});
|
if (!targetMessage) return res.status(404).json({error: "Message not found"});
|
||||||
const latestMessage = repositories.getLatestChatMessage(chatId);
|
const latestMessage = repositories.getLatestChatMessage(chatId);
|
||||||
@@ -363,6 +373,8 @@ export function createChatsRouter({repositories, chatService, modelService, conf
|
|||||||
|
|
||||||
router.post("/chats/:id/messages/by-index/:index/retry", ...chatRateLimiters, async (req, res) => {
|
router.post("/chats/:id/messages/by-index/:index/retry", ...chatRateLimiters, async (req, res) => {
|
||||||
const chatId = Number(req.params.id);
|
const chatId = Number(req.params.id);
|
||||||
|
const chat = repositories.getChat(chatId, req.session.user);
|
||||||
|
if (!chat) return res.status(404).json({error: "Chat not found"});
|
||||||
const targetMessage = chatService.getChatMessageByIndex(chatId, req.params.index);
|
const targetMessage = chatService.getChatMessageByIndex(chatId, req.params.index);
|
||||||
if (!targetMessage) return res.status(404).json({error: "Message not found"});
|
if (!targetMessage) return res.status(404).json({error: "Message not found"});
|
||||||
const latestMessage = repositories.getLatestChatMessage(chatId);
|
const latestMessage = repositories.getLatestChatMessage(chatId);
|
||||||
|
|||||||
@@ -271,8 +271,6 @@ export function createChatService(repositories, modelService, config) {
|
|||||||
|
|
||||||
const payload = this.buildMessagesPayload({user, chatId, message});
|
const payload = this.buildMessagesPayload({user, chatId, message});
|
||||||
|
|
||||||
insertChatMessage(chatId, "user", message);
|
|
||||||
repositories.touchChat(chatId, user);
|
|
||||||
const activePersona = payload.activePersona;
|
const activePersona = payload.activePersona;
|
||||||
const activeUserPersona = payload.activeUserPersona;
|
const activeUserPersona = payload.activeUserPersona;
|
||||||
const messagesPayload = payload.messagesPayload;
|
const messagesPayload = payload.messagesPayload;
|
||||||
@@ -283,6 +281,7 @@ export function createChatService(repositories, modelService, config) {
|
|||||||
|
|
||||||
if (!fullReply) return {error: "Failed to generate a valid character reply", status: 500};
|
if (!fullReply) return {error: "Failed to generate a valid character reply", status: 500};
|
||||||
|
|
||||||
|
insertChatMessage(chatId, "user", message);
|
||||||
insertChatMessage(chatId, "bot", fullReply, {
|
insertChatMessage(chatId, "bot", fullReply, {
|
||||||
retryVariants: [fullReply],
|
retryVariants: [fullReply],
|
||||||
retryActiveIndex: 0,
|
retryActiveIndex: 0,
|
||||||
@@ -299,20 +298,19 @@ export function createChatService(repositories, modelService, config) {
|
|||||||
|
|
||||||
const payload = this.buildMessagesPayload({user, chatId, message});
|
const payload = this.buildMessagesPayload({user, chatId, message});
|
||||||
|
|
||||||
insertChatMessage(chatId, "user", message);
|
|
||||||
repositories.touchChat(chatId, user);
|
|
||||||
const activePersona = payload.activePersona;
|
const activePersona = payload.activePersona;
|
||||||
const activeUserPersona = payload.activeUserPersona;
|
const activeUserPersona = payload.activeUserPersona;
|
||||||
const messagesPayload = payload.messagesPayload;
|
const messagesPayload = payload.messagesPayload;
|
||||||
|
|
||||||
|
// Persona replies must be validated before any text is exposed to the client.
|
||||||
|
// Normal chats can retain true incremental streaming.
|
||||||
const fullReply = activePersona
|
const fullReply = activePersona
|
||||||
? await modelService.streamReply(model, messagesPayload, onChunk)
|
? await generateValidatedRoleplayReply({selectedModel: model, messagesPayload, userPersona: activeUserPersona})
|
||||||
: await modelService.streamReply(model, messagesPayload, onChunk);
|
: await modelService.streamReply(model, messagesPayload, onChunk);
|
||||||
|
|
||||||
if (!fullReply) return {error: "Failed to generate a valid character reply", status: 500};
|
if (!fullReply) return {error: "Failed to generate a valid character reply", status: 500};
|
||||||
if (activePersona && containsUserVoiceInRoleplayOpener(fullReply, activeUserPersona)) {
|
if (activePersona && onChunk) onChunk(fullReply, fullReply);
|
||||||
return {error: "Failed to generate a valid character reply", status: 500};
|
insertChatMessage(chatId, "user", message);
|
||||||
}
|
|
||||||
insertChatMessage(chatId, "bot", fullReply, {
|
insertChatMessage(chatId, "bot", fullReply, {
|
||||||
retryVariants: [fullReply],
|
retryVariants: [fullReply],
|
||||||
retryActiveIndex: 0,
|
retryActiveIndex: 0,
|
||||||
@@ -327,10 +325,14 @@ export function createChatService(repositories, modelService, config) {
|
|||||||
const session = repositories.getChat(chatId, user);
|
const session = repositories.getChat(chatId, user);
|
||||||
if (!session) return {error: "Chat not found", status: 404};
|
if (!session) return {error: "Chat not found", status: 404};
|
||||||
|
|
||||||
|
const existingMessage = formatChatMessage(targetMessage);
|
||||||
|
if (existingMessage.retryRetriesUsed >= 5) {
|
||||||
|
return {error: "Maximum of 5 retries reached", status: 400};
|
||||||
|
}
|
||||||
|
|
||||||
const retryResult = await buildRetryPayload({chatId, user, session, selectedModel, targetMessage, retryStyle});
|
const retryResult = await buildRetryPayload({chatId, user, session, selectedModel, targetMessage, retryStyle});
|
||||||
if (retryResult.error) return {error: retryResult.error, status: 400};
|
if (retryResult.error) return {error: retryResult.error, status: 400};
|
||||||
|
|
||||||
const existingMessage = formatChatMessage(targetMessage);
|
|
||||||
const retryVariants = [...existingMessage.retryVariants, retryResult.fullReply];
|
const retryVariants = [...existingMessage.retryVariants, retryResult.fullReply];
|
||||||
persistChatMessageRetryState({
|
persistChatMessageRetryState({
|
||||||
chatId,
|
chatId,
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import {exec} from "child_process";
|
import {execFile} from "child_process";
|
||||||
|
|
||||||
class ModelServiceError extends Error {
|
class ModelServiceError extends Error {
|
||||||
constructor(code, message, status = 500) {
|
constructor(code, message, status = 500) {
|
||||||
@@ -29,7 +29,7 @@ export function createModelService(config, overrides = {}) {
|
|||||||
if (state.timer) clearTimeout(state.timer);
|
if (state.timer) clearTimeout(state.timer);
|
||||||
state.timer = setTimeout(() => {
|
state.timer = setTimeout(() => {
|
||||||
if (state.activeRequests > 0) return;
|
if (state.activeRequests > 0) return;
|
||||||
exec(`ollama stop ${model}`, () => {
|
execFile("ollama", ["stop", model], () => {
|
||||||
modelState.delete(model);
|
modelState.delete(model);
|
||||||
});
|
});
|
||||||
}, config.modelUnloadAfterMs);
|
}, config.modelUnloadAfterMs);
|
||||||
|
|||||||
@@ -79,13 +79,20 @@ function validateMessage(message, chatIndex, messageIndex, errors) {
|
|||||||
? message.retry_variants.map((item) => String(item ?? "")).filter(Boolean)
|
? message.retry_variants.map((item) => String(item ?? "")).filter(Boolean)
|
||||||
: [content].filter(Boolean);
|
: [content].filter(Boolean);
|
||||||
return {
|
return {
|
||||||
|
sourceId: Number.isInteger(Number(message.id)) ? Number(message.id) : null,
|
||||||
role: role === "assistant" ? "bot" : role,
|
role: role === "assistant" ? "bot" : role,
|
||||||
content,
|
content,
|
||||||
model_name: optionalText(message.model_name || message.modelName),
|
model_name: optionalText(message.model_name || message.modelName),
|
||||||
retryVariants,
|
retryVariants,
|
||||||
retryActiveIndex: Number.isInteger(Number(message.retryActiveIndex)) ? Number(message.retryActiveIndex) : 0,
|
retryActiveIndex: Number.isInteger(Number(message.retryActiveIndex ?? message.retry_active_index))
|
||||||
retryRetriesUsed: Number.isInteger(Number(message.retryRetriesUsed)) ? Number(message.retryRetriesUsed) : 0,
|
? Number(message.retryActiveIndex ?? message.retry_active_index)
|
||||||
retryPromptMessageId: Number.isInteger(Number(message.retryPromptMessageId)) ? Number(message.retryPromptMessageId) : null
|
: 0,
|
||||||
|
retryRetriesUsed: Number.isInteger(Number(message.retryRetriesUsed ?? message.retry_retries_used))
|
||||||
|
? Number(message.retryRetriesUsed ?? message.retry_retries_used)
|
||||||
|
: 0,
|
||||||
|
retryPromptMessageId: Number.isInteger(Number(message.retryPromptMessageId ?? message.retry_prompt_message_id))
|
||||||
|
? Number(message.retryPromptMessageId ?? message.retry_prompt_message_id)
|
||||||
|
: null
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user