Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion clients/brain_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -839,7 +839,8 @@ async def ask_brain_stream(
)

thinking_filter = RuntimeActionStreamFilter(
enabled_actions=enabled_actions
enabled_actions=enabled_actions,
preserve_action_text=True,
)
content_filter = RuntimeActionStreamFilter(
enabled_actions=enabled_actions
Expand Down Expand Up @@ -902,6 +903,16 @@ async def filter_runtime_action_chunk(
)

stop_for_runtime_action = True

if (
chunk_type == "thinking"
and result.text
):
return {
**action_chunk,
"content": result.text,
}

return None

if not result.text:
Expand Down
18 changes: 13 additions & 5 deletions clients/service_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,24 @@ async def ask_service_model(
system_prompt: str = "",
temperature: float,
max_tokens: int,
timeout: float | None = None,
):

return await client.ask(
system_prompt=(
request = {
"system_prompt": (
system_prompt
or build_service_system_prompt()
),
user_prompt=user_prompt,
temperature=temperature,
max_tokens=max_tokens,
"user_prompt": user_prompt,
"temperature": temperature,
"max_tokens": max_tokens,
}

if timeout is not None:
request["timeout"] = timeout

return await client.ask(
**request
)


Expand Down
12 changes: 8 additions & 4 deletions config.example.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@

BRAIN_REQUEST_TIMEOUT = 200.0

BRAIN_CONTEXT_WINDOW = 32768
BRAIN_CONTEXT_WINDOW = 8192

NIGHT_BRAIN_CONTEXT_WINDOW = 16384

BRAIN_TEMPERATURE = 0.7

Expand All @@ -31,9 +33,11 @@

SERVICE_REQUEST_TIMEOUT = 200.0

SERVICE_CONTEXT_WINDOW = 8192
RUNTIME_MEMORY_REQUEST_TIMEOUT = 120.0

SERVICE_CONTEXT_WINDOW = 4096

SERVICE_TEMPERATURE = 0.15
SERVICE_TEMPERATURE = 0.1

SERVICE_MAX_TOKENS = 1024

Expand All @@ -60,7 +64,7 @@

TRANSLATOR_REQUEST_TIMEOUT = 120

TRANSLATOR_CONTEXT_WINDOW = 4096
TRANSLATOR_CONTEXT_WINDOW = 2048

TRANSLATION_RETRIES = 1

Expand Down
80 changes: 58 additions & 22 deletions memory/message_memory.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import asyncio
import contextlib
import traceback

from clients.service_client import (
ask_service_model,
Expand All @@ -11,6 +12,41 @@
ResponseExtractor,
)


DEFAULT_RUNTIME_MEMORY = (
"This session has just begun. "
"You have no history with the user yet."
)


DEFAULT_MEMORY_REQUEST_TIMEOUT = 120.0


def get_memory_request_timeout() -> float:

configured_timeout = getattr(
config,
"RUNTIME_MEMORY_REQUEST_TIMEOUT",
None,
)

if configured_timeout is None:
configured_timeout = max(
float(
getattr(
config,
"SERVICE_REQUEST_TIMEOUT",
0.0,
)
),
DEFAULT_MEMORY_REQUEST_TIMEOUT,
)

return float(
configured_timeout
)


async def safe_call(
call,
*args,
Expand Down Expand Up @@ -70,8 +106,8 @@ def build_runtime_memory_system_prompt() -> str:
"Do not explain your reasoning or the summarization process.\n"
"Write memory as atomic bullet lines, one semantic entity per line.\n"
"Each line should start with a compact semantic label such as topic, "
"user intent, active topic, open reference, pending choice, offered options, "
"preference, decision, pattern, or interrupted response.\n"
"user intents, potential motifs, focus, priority, active topics, open references, pending choices, "
"offered options, preferences, expectations, current concern, decisions, patterns, failures or interruptions.\n"
"Avoid writing about JIN's role unless the role itself changed or matters. "
"Describe assistant actions neutrally instead.\n"
"Keep memory actionable: write what helps the next answer, not a recap of "
Expand Down Expand Up @@ -100,21 +136,20 @@ def build_runtime_memory_system_prompt() -> str:
"Prefer compact continuity over transcript-like detail.\n"
"Remove noise, implementation chatter, and one-off details unless they change "
"what JIN should understand next.\n"
"Keep the memory under 1200 characters unless the latest turn is highly important.\n"
"The final memory should feel like live state, not chat history.\n"
"The final memory snapshot should feel like current live trusted state.\n"
)


def build_runtime_memory_user_prompt(
*,
current_memory: str,
user_message: str,
assistant_message: str,
*,
current_memory: str,
user_message: str,
assistant_message: str,
) -> str:

return (
"Current runtime memory:\n"
f"{current_memory.strip() or 'User and JIN just started interacting.'}\n\n"
f"{current_memory.strip() or DEFAULT_RUNTIME_MEMORY}\n\n"
"Latest user message:\n"
f"{user_message.strip()}\n\n"
"Latest JIN answer:\n"
Expand Down Expand Up @@ -250,6 +285,7 @@ async def ask_runtime_memory_model(
max_tokens=(
config.SERVICE_MAX_TOKENS
),
timeout=get_memory_request_timeout(),
)


Expand Down Expand Up @@ -328,17 +364,15 @@ async def summarize_runtime_memory(
)

return current_memory
updates_counter = getattr(
context,
"runtime_memory_updates",
0,
)

if updated_memory:
if updated_memory or updates_counter == 0:
context.runtime_memory = updated_memory
context.runtime_memory_updates = (
getattr(
context,
"runtime_memory_updates",
0,
)
+ 1
)
context.runtime_memory_updates = updates_counter + 1

logger = getattr(
context,
Expand Down Expand Up @@ -369,7 +403,11 @@ async def summarize_runtime_memory(
except asyncio.CancelledError:
raise

except Exception as error:
except Exception:
formatted_traceback = (
traceback.format_exc()
)

logger = getattr(
context,
"logger",
Expand All @@ -384,9 +422,7 @@ async def summarize_runtime_memory(
await safe_call(
log_error,
"[MEMORY] runtime memory update failed",
details=str(
error
),
details=formatted_traceback,
)

return getattr(
Expand Down
7 changes: 6 additions & 1 deletion runtime/runtime_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ async def ask(
user_prompt: str,
temperature: float,
max_tokens: int,
timeout: float | None = None,
):

payload = self.build_payload(
Expand All @@ -99,7 +100,11 @@ async def ask(
settings.CHAT_ENDPOINT,
),
json=payload,
timeout=self.timeout,
timeout=(
self.timeout
if timeout is None
else timeout
),
)

response.raise_for_status()
Expand Down
8 changes: 5 additions & 3 deletions runtime/runtime_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
RuntimeEmitter,
)

from memory.message_memory import (
DEFAULT_RUNTIME_MEMORY,
)


@dataclass
class RuntimeContext:
Expand Down Expand Up @@ -44,9 +48,7 @@ class RuntimeContext:
default_factory=list
)

runtime_memory: str = (
"User and JIN just started interacting."
)
runtime_memory: str = DEFAULT_RUNTIME_MEMORY

runtime_memory_updates: int = 0

Expand Down
2 changes: 1 addition & 1 deletion templates/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,7 @@ <h2 class="text-xs font-bold uppercase tracking-widest text-zinc-300">

<pre
id="runtime-memory-text"
class="min-h-28 whitespace-pre-wrap break-words text-[11px] leading-relaxed text-zinc-100">User and JIN just started interacting.</pre>
class="min-h-28 whitespace-pre-wrap break-words text-[11px] leading-relaxed text-zinc-100">This session has just begun. You have no history with the user yet.</pre>

</div>

Expand Down
Loading