refac
This commit is contained in:
1 parent
33cf3fbb7f
commit
1f5b0d816f
9 files changed
+103
-31
No files matched your search
@@ -2143,6 +2143,10 @@ CONTEXT_COMPACTION_TOKEN_THRESHOLD = int(os.getenv('CONTEXT_COMPACTION_TOKEN_THR
|
|||||||
_CONTEXT_COMPACTION_TOKEN_CAP = os.getenv('CONTEXT_COMPACTION_TOKEN_CAP')
|
_CONTEXT_COMPACTION_TOKEN_CAP = os.getenv('CONTEXT_COMPACTION_TOKEN_CAP')
|
||||||
CONTEXT_COMPACTION_TOKEN_CAP = int(_CONTEXT_COMPACTION_TOKEN_CAP) if _CONTEXT_COMPACTION_TOKEN_CAP else None
|
CONTEXT_COMPACTION_TOKEN_CAP = int(_CONTEXT_COMPACTION_TOKEN_CAP) if _CONTEXT_COMPACTION_TOKEN_CAP else None
|
||||||
|
|
||||||
|
CONTEXT_COMPACTION_RETENTION_PERCENTAGE = min(
|
||||||
|
50, max(10, int(os.getenv('CONTEXT_COMPACTION_RETENTION_PERCENTAGE', '40')))
|
||||||
|
)
|
||||||
|
|
||||||
CONTEXT_COMPACTION_PROMPT_TEMPLATE = os.getenv('CONTEXT_COMPACTION_PROMPT_TEMPLATE', '')
|
CONTEXT_COMPACTION_PROMPT_TEMPLATE = os.getenv('CONTEXT_COMPACTION_PROMPT_TEMPLATE', '')
|
||||||
|
|
||||||
TITLE_GENERATION_PROMPT_TEMPLATE = os.getenv('TITLE_GENERATION_PROMPT_TEMPLATE', '')
|
TITLE_GENERATION_PROMPT_TEMPLATE = os.getenv('TITLE_GENERATION_PROMPT_TEMPLATE', '')
|
||||||
@@ -3054,6 +3058,7 @@ DEFAULT_CONFIG = {
|
|||||||
'chat.context_compaction.enable': ENABLE_CONTEXT_COMPACTION,
|
'chat.context_compaction.enable': ENABLE_CONTEXT_COMPACTION,
|
||||||
'chat.context_compaction.token_threshold': CONTEXT_COMPACTION_TOKEN_THRESHOLD,
|
'chat.context_compaction.token_threshold': CONTEXT_COMPACTION_TOKEN_THRESHOLD,
|
||||||
'chat.context_compaction.token_cap': CONTEXT_COMPACTION_TOKEN_CAP,
|
'chat.context_compaction.token_cap': CONTEXT_COMPACTION_TOKEN_CAP,
|
||||||
|
'chat.context_compaction.retention_percentage': CONTEXT_COMPACTION_RETENTION_PERCENTAGE,
|
||||||
'chat.context_compaction.prompt_template': CONTEXT_COMPACTION_PROMPT_TEMPLATE,
|
'chat.context_compaction.prompt_template': CONTEXT_COMPACTION_PROMPT_TEMPLATE,
|
||||||
'task.title.prompt_template': TITLE_GENERATION_PROMPT_TEMPLATE,
|
'task.title.prompt_template': TITLE_GENERATION_PROMPT_TEMPLATE,
|
||||||
'task.tags.prompt_template': TAGS_GENERATION_PROMPT_TEMPLATE,
|
'task.tags.prompt_template': TAGS_GENERATION_PROMPT_TEMPLATE,
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ from open_webui.models.automations import AutomationRun
|
|||||||
from open_webui.models.chat_messages import ChatMessage, ChatMessages
|
from open_webui.models.chat_messages import ChatMessage, ChatMessages
|
||||||
from open_webui.models.folders import Folders
|
from open_webui.models.folders import Folders
|
||||||
from open_webui.models.tags import Tag, TagModel, Tags
|
from open_webui.models.tags import Tag, TagModel, Tags
|
||||||
from open_webui.utils.misc import sanitize_data_for_db, sanitize_text_for_db
|
from open_webui.utils.misc import get_output_text, sanitize_data_for_db, sanitize_text_for_db
|
||||||
from pydantic import BaseModel, ConfigDict, field_validator
|
from pydantic import BaseModel, ConfigDict, field_validator
|
||||||
from sqlalchemy import (
|
from sqlalchemy import (
|
||||||
JSON,
|
JSON,
|
||||||
@@ -840,6 +840,11 @@ class ChatTable:
|
|||||||
if chat is None:
|
if chat is None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
if not message.get('content'):
|
||||||
|
output_text = get_output_text(message.get('output'))
|
||||||
|
if output_text:
|
||||||
|
message['content'] = output_text
|
||||||
|
|
||||||
# Sanitize message content for null characters before upserting
|
# Sanitize message content for null characters before upserting
|
||||||
if isinstance(message.get('content'), str):
|
if isinstance(message.get('content'), str):
|
||||||
message['content'] = sanitize_text_for_db(message['content'])
|
message['content'] = sanitize_text_for_db(message['content'])
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ from open_webui.retrieval.web.utils import get_web_loader
|
|||||||
from open_webui.utils.access_control.files import has_access_to_file
|
from open_webui.utils.access_control.files import has_access_to_file
|
||||||
from open_webui.utils.access_control.folders import has_folder_access
|
from open_webui.utils.access_control.folders import has_folder_access
|
||||||
from open_webui.utils.headers import include_user_info_headers
|
from open_webui.utils.headers import include_user_info_headers
|
||||||
from open_webui.utils.misc import get_message_list
|
from open_webui.utils.misc import get_content_from_message, get_message_list
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -1409,7 +1409,10 @@ async def get_sources_from_items(
|
|||||||
# Reconstruct the message list in order
|
# Reconstruct the message list in order
|
||||||
message_list = get_message_list(messages_map, message_id)
|
message_list = get_message_list(messages_map, message_id)
|
||||||
message_history = '\n'.join(
|
message_history = '\n'.join(
|
||||||
[f'#### {m.get("role", "user").capitalize()}\n{m.get("content")}\n' for m in message_list]
|
[
|
||||||
|
f'#### {m.get("role", "user").capitalize()}\n{get_content_from_message(m) or ""}\n'
|
||||||
|
for m in message_list
|
||||||
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
# User has access to the chat
|
# User has access to the chat
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ CHAT_CONFIG_KEYS = {
|
|||||||
'ENABLE_CONTEXT_COMPACTION': 'chat.context_compaction.enable',
|
'ENABLE_CONTEXT_COMPACTION': 'chat.context_compaction.enable',
|
||||||
'CONTEXT_COMPACTION_TOKEN_THRESHOLD': 'chat.context_compaction.token_threshold',
|
'CONTEXT_COMPACTION_TOKEN_THRESHOLD': 'chat.context_compaction.token_threshold',
|
||||||
'CONTEXT_COMPACTION_TOKEN_CAP': 'chat.context_compaction.token_cap',
|
'CONTEXT_COMPACTION_TOKEN_CAP': 'chat.context_compaction.token_cap',
|
||||||
|
'CONTEXT_COMPACTION_RETENTION_PERCENTAGE': 'chat.context_compaction.retention_percentage',
|
||||||
'CONTEXT_COMPACTION_PROMPT_TEMPLATE': 'chat.context_compaction.prompt_template',
|
'CONTEXT_COMPACTION_PROMPT_TEMPLATE': 'chat.context_compaction.prompt_template',
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,6 +77,7 @@ class ChatConfigForm(BaseModel):
|
|||||||
ENABLE_CONTEXT_COMPACTION: bool
|
ENABLE_CONTEXT_COMPACTION: bool
|
||||||
CONTEXT_COMPACTION_TOKEN_THRESHOLD: int
|
CONTEXT_COMPACTION_TOKEN_THRESHOLD: int
|
||||||
CONTEXT_COMPACTION_TOKEN_CAP: int | None = None
|
CONTEXT_COMPACTION_TOKEN_CAP: int | None = None
|
||||||
|
CONTEXT_COMPACTION_RETENTION_PERCENTAGE: int = 40
|
||||||
CONTEXT_COMPACTION_PROMPT_TEMPLATE: str
|
CONTEXT_COMPACTION_PROMPT_TEMPLATE: str
|
||||||
|
|
||||||
|
|
||||||
@@ -125,6 +127,8 @@ async def get_chat_config_values() -> dict:
|
|||||||
config = {field: values[storage_key] for field, storage_key in CHAT_CONFIG_KEYS.items() if storage_key in values}
|
config = {field: values[storage_key] for field, storage_key in CHAT_CONFIG_KEYS.items() if storage_key in values}
|
||||||
if config.get('CONTEXT_COMPACTION_TOKEN_CAP') is None:
|
if config.get('CONTEXT_COMPACTION_TOKEN_CAP') is None:
|
||||||
config['CONTEXT_COMPACTION_TOKEN_CAP'] = config.get('CONTEXT_COMPACTION_TOKEN_THRESHOLD', 80000)
|
config['CONTEXT_COMPACTION_TOKEN_CAP'] = config.get('CONTEXT_COMPACTION_TOKEN_THRESHOLD', 80000)
|
||||||
|
if config.get('CONTEXT_COMPACTION_RETENTION_PERCENTAGE') is None:
|
||||||
|
config['CONTEXT_COMPACTION_RETENTION_PERCENTAGE'] = 40
|
||||||
return config
|
return config
|
||||||
|
|
||||||
|
|
||||||
@@ -738,12 +742,14 @@ async def get_chat_config(user=Depends(get_admin_user)):
|
|||||||
async def set_chat_config(form_data: ChatConfigForm, user=Depends(get_admin_user)):
|
async def set_chat_config(form_data: ChatConfigForm, user=Depends(get_admin_user)):
|
||||||
threshold = max(1, int(form_data.CONTEXT_COMPACTION_TOKEN_THRESHOLD))
|
threshold = max(1, int(form_data.CONTEXT_COMPACTION_TOKEN_THRESHOLD))
|
||||||
token_cap = max(1, int(form_data.CONTEXT_COMPACTION_TOKEN_CAP or threshold))
|
token_cap = max(1, int(form_data.CONTEXT_COMPACTION_TOKEN_CAP or threshold))
|
||||||
|
retention_percentage = min(50, max(10, int(form_data.CONTEXT_COMPACTION_RETENTION_PERCENTAGE)))
|
||||||
await Config.upsert(
|
await Config.upsert(
|
||||||
chat_config_updates(
|
chat_config_updates(
|
||||||
{
|
{
|
||||||
**form_data.model_dump(),
|
**form_data.model_dump(),
|
||||||
'CONTEXT_COMPACTION_TOKEN_THRESHOLD': threshold,
|
'CONTEXT_COMPACTION_TOKEN_THRESHOLD': threshold,
|
||||||
'CONTEXT_COMPACTION_TOKEN_CAP': token_cap,
|
'CONTEXT_COMPACTION_TOKEN_CAP': token_cap,
|
||||||
|
'CONTEXT_COMPACTION_RETENTION_PERCENTAGE': retention_percentage,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ async def compact_messages_for_request(
|
|||||||
if not _exceeds_token_threshold(messages, system_prompt, previous_summary, token_threshold) or len(messages) <= 3:
|
if not _exceeds_token_threshold(messages, system_prompt, previous_summary, token_threshold) or len(messages) <= 3:
|
||||||
return messages, previous_summary, False
|
return messages, previous_summary, False
|
||||||
|
|
||||||
boundary = _find_compaction_boundary(messages)
|
boundary = _find_compaction_boundary(messages, config['retention_percentage'])
|
||||||
compacted_messages = messages[:boundary]
|
compacted_messages = messages[:boundary]
|
||||||
recent_messages = messages[boundary:]
|
recent_messages = messages[boundary:]
|
||||||
if not compacted_messages or not recent_messages:
|
if not compacted_messages or not recent_messages:
|
||||||
@@ -196,6 +196,7 @@ async def _load_config() -> dict:
|
|||||||
'chat.context_compaction.enable',
|
'chat.context_compaction.enable',
|
||||||
'chat.context_compaction.token_threshold',
|
'chat.context_compaction.token_threshold',
|
||||||
'chat.context_compaction.token_cap',
|
'chat.context_compaction.token_cap',
|
||||||
|
'chat.context_compaction.retention_percentage',
|
||||||
'chat.context_compaction.prompt_template',
|
'chat.context_compaction.prompt_template',
|
||||||
)
|
)
|
||||||
token_threshold = _parse_positive_int(values.get('chat.context_compaction.token_threshold')) or 80000
|
token_threshold = _parse_positive_int(values.get('chat.context_compaction.token_threshold')) or 80000
|
||||||
@@ -203,6 +204,9 @@ async def _load_config() -> dict:
|
|||||||
'enable': bool(values.get('chat.context_compaction.enable', False)),
|
'enable': bool(values.get('chat.context_compaction.enable', False)),
|
||||||
'token_threshold': token_threshold,
|
'token_threshold': token_threshold,
|
||||||
'token_cap': _parse_positive_int(values.get('chat.context_compaction.token_cap')) or token_threshold,
|
'token_cap': _parse_positive_int(values.get('chat.context_compaction.token_cap')) or token_threshold,
|
||||||
|
'retention_percentage': _clamp_retention_percentage(
|
||||||
|
values.get('chat.context_compaction.retention_percentage')
|
||||||
|
),
|
||||||
'prompt_template': values.get('chat.context_compaction.prompt_template', '') or '',
|
'prompt_template': values.get('chat.context_compaction.prompt_template', '') or '',
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -215,6 +219,14 @@ def _parse_positive_int(value: Any) -> int | None:
|
|||||||
return parsed if parsed > 0 else None
|
return parsed if parsed > 0 else None
|
||||||
|
|
||||||
|
|
||||||
|
def _clamp_retention_percentage(value: Any) -> int:
|
||||||
|
try:
|
||||||
|
parsed = int(value)
|
||||||
|
except (TypeError, ValueError):
|
||||||
|
parsed = 40
|
||||||
|
return min(50, max(10, parsed))
|
||||||
|
|
||||||
|
|
||||||
def _resolve_token_threshold(global_threshold: int, global_cap: int, metadata: dict) -> int:
|
def _resolve_token_threshold(global_threshold: int, global_cap: int, metadata: dict) -> int:
|
||||||
configured_threshold = _parse_positive_int((metadata.get('params') or {}).get('compact_token_threshold'))
|
configured_threshold = _parse_positive_int((metadata.get('params') or {}).get('compact_token_threshold'))
|
||||||
return min(configured_threshold or global_threshold, global_cap)
|
return min(configured_threshold or global_threshold, global_cap)
|
||||||
@@ -297,8 +309,9 @@ def _exceeds_token_threshold(messages: list[dict], system_prompt: str, summary:
|
|||||||
return estimated > threshold
|
return estimated > threshold
|
||||||
|
|
||||||
|
|
||||||
def _find_compaction_boundary(messages: list[dict]) -> int:
|
def _find_compaction_boundary(messages: list[dict], retention_percentage: int = 40) -> int:
|
||||||
keep_count = max(2, len(messages) * 2 // 5)
|
retention_percentage = _clamp_retention_percentage(retention_percentage)
|
||||||
|
keep_count = max(2, len(messages) * retention_percentage // 100)
|
||||||
target = max(1, len(messages) - keep_count)
|
target = max(1, len(messages) - keep_count)
|
||||||
boundaries = [idx for idx, message in enumerate(messages) if message.get('role') == 'user'][1:]
|
boundaries = [idx for idx, message in enumerate(messages) if message.get('role') == 'user'][1:]
|
||||||
return next((idx for idx in reversed(boundaries) if idx <= target), 0)
|
return next((idx for idx in reversed(boundaries) if idx <= target), 0)
|
||||||
|
|||||||
@@ -107,6 +107,7 @@ from open_webui.utils.misc import (
|
|||||||
get_last_user_message,
|
get_last_user_message,
|
||||||
get_last_user_message_item,
|
get_last_user_message_item,
|
||||||
get_message_list,
|
get_message_list,
|
||||||
|
get_output_text,
|
||||||
get_system_message,
|
get_system_message,
|
||||||
is_string_allowed,
|
is_string_allowed,
|
||||||
merge_system_messages,
|
merge_system_messages,
|
||||||
@@ -137,17 +138,6 @@ logging.basicConfig(stream=sys.stdout, level=GLOBAL_LOG_LEVEL)
|
|||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def _last_output_text(output: list | None) -> str:
|
|
||||||
for item in reversed(output or []):
|
|
||||||
if item.get('type') != 'message':
|
|
||||||
continue
|
|
||||||
parts = item.get('content') or []
|
|
||||||
text = ''.join(str(part.get('text') or '') for part in parts if part.get('type') == 'output_text')
|
|
||||||
if text:
|
|
||||||
return text
|
|
||||||
return ''
|
|
||||||
|
|
||||||
|
|
||||||
async def publish_chat_finished_event(
|
async def publish_chat_finished_event(
|
||||||
request: Request, user: UserModel, metadata: dict, title: str, content: str, output: list | None = None
|
request: Request, user: UserModel, metadata: dict, title: str, content: str, output: list | None = None
|
||||||
):
|
):
|
||||||
@@ -155,7 +145,7 @@ async def publish_chat_finished_event(
|
|||||||
if getattr(request.state, 'internal', False) is True or not chat_id or chat_id.startswith(('channel:', 'local:')):
|
if getattr(request.state, 'internal', False) is True or not chat_id or chat_id.startswith(('channel:', 'local:')):
|
||||||
return
|
return
|
||||||
|
|
||||||
content = content or _last_output_text(output)
|
content = content or get_output_text(output)
|
||||||
webui_url = await Config.get('webui.url')
|
webui_url = await Config.get('webui.url')
|
||||||
await publish_event(
|
await publish_event(
|
||||||
request,
|
request,
|
||||||
@@ -3398,7 +3388,7 @@ async def outlet_filter_handler(ctx):
|
|||||||
message_list = [
|
message_list = [
|
||||||
{
|
{
|
||||||
'role': m.get('role'),
|
'role': m.get('role'),
|
||||||
'content': m.get('content', ''),
|
'content': m.get('content') or get_output_text(m.get('output')),
|
||||||
}
|
}
|
||||||
for m in form_messages
|
for m in form_messages
|
||||||
]
|
]
|
||||||
@@ -3431,7 +3421,7 @@ async def outlet_filter_handler(ctx):
|
|||||||
{
|
{
|
||||||
'id': m.get('id'),
|
'id': m.get('id'),
|
||||||
'role': m.get('role'),
|
'role': m.get('role'),
|
||||||
'content': m.get('content', ''),
|
'content': m.get('content') or get_output_text(m.get('output')),
|
||||||
'info': m.get('info'),
|
'info': m.get('info'),
|
||||||
'timestamp': m.get('timestamp'),
|
'timestamp': m.get('timestamp'),
|
||||||
**({'output': m['output']} if m.get('output') else {}),
|
**({'output': m['output']} if m.get('output') else {}),
|
||||||
@@ -3483,17 +3473,21 @@ async def outlet_filter_handler(ctx):
|
|||||||
outlet_message_id = message.get('id')
|
outlet_message_id = message.get('id')
|
||||||
if outlet_message_id and outlet_message_id in messages_map:
|
if outlet_message_id and outlet_message_id in messages_map:
|
||||||
original_message = messages_map[outlet_message_id]
|
original_message = messages_map[outlet_message_id]
|
||||||
content_changed = original_message.get('content') != message.get('content')
|
original_content = original_message.get('content') or get_output_text(
|
||||||
|
original_message.get('output')
|
||||||
|
)
|
||||||
|
message_content = message.get('content') or get_output_text(message.get('output'))
|
||||||
|
content_changed = original_content != message_content
|
||||||
output_changed = message.get('output') and message.get('output') != original_message.get(
|
output_changed = message.get('output') and message.get('output') != original_message.get(
|
||||||
'output'
|
'output'
|
||||||
)
|
)
|
||||||
if content_changed or output_changed:
|
if content_changed or output_changed:
|
||||||
message_update = {
|
message_update = {
|
||||||
'originalContent': original_message.get('content'),
|
'originalContent': original_content,
|
||||||
**({'output': message['output']} if output_changed else {}),
|
**({'output': message['output']} if output_changed else {}),
|
||||||
}
|
}
|
||||||
if content_changed:
|
if content_changed:
|
||||||
message_update['content'] = message.get('content', '')
|
message_update['content'] = message_content or ''
|
||||||
await Chats.upsert_message_to_chat_by_id_and_message_id(
|
await Chats.upsert_message_to_chat_by_id_and_message_id(
|
||||||
chat_id,
|
chat_id,
|
||||||
outlet_message_id,
|
outlet_message_id,
|
||||||
|
|||||||
@@ -160,13 +160,40 @@ def get_last_user_message_item(messages: list[dict]) -> dict | None:
|
|||||||
|
|
||||||
|
|
||||||
def get_content_from_message(message: dict) -> str | None:
|
def get_content_from_message(message: dict) -> str | None:
|
||||||
if isinstance(message.get('content'), list):
|
content = message.get('content')
|
||||||
for item in message['content']:
|
if isinstance(content, list):
|
||||||
if item['type'] == 'text':
|
for item in content:
|
||||||
return item['text']
|
if isinstance(item, dict) and item.get('type') == 'text':
|
||||||
else:
|
return item.get('text')
|
||||||
return message.get('content')
|
elif content:
|
||||||
return None
|
return content
|
||||||
|
|
||||||
|
output_text = get_output_text(message.get('output'))
|
||||||
|
return output_text or (content if isinstance(content, str) else None)
|
||||||
|
|
||||||
|
|
||||||
|
def get_output_text(output: list | None) -> str:
|
||||||
|
if not isinstance(output, list):
|
||||||
|
return ''
|
||||||
|
|
||||||
|
texts = []
|
||||||
|
for item in output:
|
||||||
|
if not isinstance(item, dict) or item.get('type') != 'message':
|
||||||
|
continue
|
||||||
|
|
||||||
|
parts = item.get('content') or []
|
||||||
|
if not isinstance(parts, list):
|
||||||
|
continue
|
||||||
|
|
||||||
|
text = ''.join(
|
||||||
|
str(part.get('text'))
|
||||||
|
for part in parts
|
||||||
|
if isinstance(part, dict) and part.get('text') is not None
|
||||||
|
)
|
||||||
|
if text.strip():
|
||||||
|
texts.append(text)
|
||||||
|
|
||||||
|
return '\n'.join(texts)
|
||||||
|
|
||||||
|
|
||||||
def reconcile_tool_pairs(messages: list[dict]) -> list[dict]:
|
def reconcile_tool_pairs(messages: list[dict]) -> list[dict]:
|
||||||
@@ -213,7 +240,7 @@ def reconcile_tool_pairs(messages: list[dict]) -> list[dict]:
|
|||||||
|
|
||||||
# All tool_calls were orphans — keep the message only if it
|
# All tool_calls were orphans — keep the message only if it
|
||||||
# carries meaningful text or reasoning content.
|
# carries meaningful text or reasoning content.
|
||||||
content = message.get('content', '')
|
content = get_content_from_message(message) or ''
|
||||||
has_meaningful_content = content.strip() if isinstance(content, str) else content
|
has_meaningful_content = content.strip() if isinstance(content, str) else content
|
||||||
if has_meaningful_content or message.get('reasoning_content'):
|
if has_meaningful_content or message.get('reasoning_content'):
|
||||||
reconciled_messages.append({key: value for key, value in message.items() if key != 'tool_calls'})
|
reconciled_messages.append({key: value for key, value in message.items() if key != 'tool_calls'})
|
||||||
|
|||||||
@@ -44,6 +44,7 @@
|
|||||||
ENABLE_CONTEXT_COMPACTION: false,
|
ENABLE_CONTEXT_COMPACTION: false,
|
||||||
CONTEXT_COMPACTION_TOKEN_THRESHOLD: 80000,
|
CONTEXT_COMPACTION_TOKEN_THRESHOLD: 80000,
|
||||||
CONTEXT_COMPACTION_TOKEN_CAP: 80000,
|
CONTEXT_COMPACTION_TOKEN_CAP: 80000,
|
||||||
|
CONTEXT_COMPACTION_RETENTION_PERCENTAGE: 40,
|
||||||
CONTEXT_COMPACTION_PROMPT_TEMPLATE: ''
|
CONTEXT_COMPACTION_PROMPT_TEMPLATE: ''
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -273,6 +274,22 @@
|
|||||||
/>
|
/>
|
||||||
</AdminSettingField>
|
</AdminSettingField>
|
||||||
|
|
||||||
|
<AdminSettingField
|
||||||
|
label={$i18n.t('Retained Messages')}
|
||||||
|
description={$i18n.t(
|
||||||
|
'Percentage of recent messages to keep after older messages are summarized.'
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
min="10"
|
||||||
|
max="50"
|
||||||
|
step="1"
|
||||||
|
class={inputClass}
|
||||||
|
bind:value={chatConfig.CONTEXT_COMPACTION_RETENTION_PERCENTAGE}
|
||||||
|
/>
|
||||||
|
</AdminSettingField>
|
||||||
|
|
||||||
<AdminSettingField
|
<AdminSettingField
|
||||||
label={$i18n.t('Context Compaction Prompt')}
|
label={$i18n.t('Context Compaction Prompt')}
|
||||||
description={$i18n.t(
|
description={$i18n.t(
|
||||||
|
|||||||
@@ -1975,6 +1975,7 @@
|
|||||||
"Pending User Overlay Content": "",
|
"Pending User Overlay Content": "",
|
||||||
"Pending User Overlay Title": "",
|
"Pending User Overlay Title": "",
|
||||||
"Permanently delete every chat after confirmation.": "",
|
"Permanently delete every chat after confirmation.": "",
|
||||||
|
"Percentage of recent messages to keep after older messages are summarized.": "Percentage of recent messages to keep after older messages are summarised.",
|
||||||
"Permission denied when accessing media devices": "",
|
"Permission denied when accessing media devices": "",
|
||||||
"Permission denied when accessing microphone": "",
|
"Permission denied when accessing microphone": "",
|
||||||
"Permission denied when accessing microphone: {{error}}": "",
|
"Permission denied when accessing microphone: {{error}}": "",
|
||||||
@@ -2155,6 +2156,7 @@
|
|||||||
"Render Markdown in User Messages": "",
|
"Render Markdown in User Messages": "",
|
||||||
"Render messages in compact bubble containers.": "",
|
"Render messages in compact bubble containers.": "",
|
||||||
"Repeat": "",
|
"Repeat": "",
|
||||||
|
"Retained Messages": "",
|
||||||
"Reply": "",
|
"Reply": "",
|
||||||
"Reply in Thread": "",
|
"Reply in Thread": "",
|
||||||
"Reply to thread...": "",
|
"Reply to thread...": "",
|
||||||
|
|||||||
Reference in new issue
Block a user