feat: build chat identity line from settings instead of a static env var
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01V57jSQPqwkGG8BuAXg59X5
This commit is contained in:
parent
a904f2f8e0
commit
9505bc2eb3
|
|
@ -56,11 +56,6 @@ EMAIL_SMTP_HOST = os.getenv("EMAIL_SMTP_HOST")
|
|||
EMAIL_SMTP_PORT = int(os.getenv("EMAIL_SMTP_PORT", "465"))
|
||||
EMAIL_USER = os.getenv("EMAIL_USER")
|
||||
EMAIL_PASSWORD = os.getenv("EMAIL_PASSWORD")
|
||||
CLAUDE_SYSTEM_PROMPT = os.getenv(
|
||||
"CLAUDE_SYSTEM_PROMPT",
|
||||
"Du bist JARVIS, ein KI-Assistent fuer Business-Automatisierung.",
|
||||
)
|
||||
|
||||
# ============ INITIALIZATION ============
|
||||
app = FastAPI(
|
||||
title="JARVIS API",
|
||||
|
|
@ -1070,12 +1065,21 @@ async def execute_tool(name: str, tool_input: dict) -> str:
|
|||
MAX_TOOL_ROUNDS = 5
|
||||
|
||||
|
||||
async def _identity_system_prompt() -> str:
|
||||
settings = await get_all_settings()
|
||||
return (
|
||||
f"Du bist {settings['assistant_name']}, der KI-Assistent von "
|
||||
f"{settings['company_name']}. Bei Fragen zur Erreichbarkeit kannst "
|
||||
f"du auf {settings['contact_email']} verweisen."
|
||||
)
|
||||
|
||||
|
||||
async def run_chat_completion(claude_messages: list, conversation_id: int):
|
||||
latest_user_message = claude_messages[-1]["content"]
|
||||
memory_context = await build_memory_context(latest_user_message, conversation_id)
|
||||
|
||||
system_prompt = (
|
||||
f"{CLAUDE_SYSTEM_PROMPT}\n\n{_current_datetime_context()}\n\n{CALENDAR_ASSISTANT_INSTRUCTIONS}\n\n"
|
||||
f"{await _identity_system_prompt()}\n\n{_current_datetime_context()}\n\n{CALENDAR_ASSISTANT_INSTRUCTIONS}\n\n"
|
||||
f"{MEMORY_ASSISTANT_INSTRUCTIONS}\n\n{ORDER_ASSISTANT_INSTRUCTIONS}"
|
||||
)
|
||||
if memory_context:
|
||||
|
|
|
|||
|
|
@ -43,7 +43,9 @@ async def test_run_chat_completion_without_tool_use():
|
|||
main.claude_client = MagicMock()
|
||||
main.claude_client.messages.create.return_value = completion
|
||||
|
||||
with patch.object(main, "build_memory_context", new=AsyncMock(return_value="")):
|
||||
with patch.object(main, "build_memory_context", new=AsyncMock(return_value="")), patch.object(
|
||||
main, "_identity_system_prompt", new=AsyncMock(return_value="Du bist JARVIS.")
|
||||
):
|
||||
text, output_tokens, total_tokens = await main.run_chat_completion(
|
||||
[{"role": "user", "content": "Hi"}], conversation_id=1
|
||||
)
|
||||
|
|
@ -70,7 +72,7 @@ async def test_run_chat_completion_executes_tool_and_returns_followup():
|
|||
|
||||
with patch.object(main, "list_upcoming_events", new=AsyncMock(return_value=[])), patch.object(
|
||||
main, "build_memory_context", new=AsyncMock(return_value="")
|
||||
):
|
||||
), patch.object(main, "_identity_system_prompt", new=AsyncMock(return_value="Du bist JARVIS.")):
|
||||
text, output_tokens, total_tokens = await main.run_chat_completion(
|
||||
[{"role": "user", "content": "Was steht diese Woche an?"}], conversation_id=1
|
||||
)
|
||||
|
|
@ -108,7 +110,9 @@ async def test_run_chat_completion_handles_two_sequential_tool_calls():
|
|||
|
||||
with patch.object(main, "list_upcoming_events", new=AsyncMock(return_value=[{"uid": "abc"}])), patch.object(
|
||||
main, "update_event", new=AsyncMock(return_value={"uid": "abc"})
|
||||
), patch.object(main, "build_memory_context", new=AsyncMock(return_value="")):
|
||||
), patch.object(main, "build_memory_context", new=AsyncMock(return_value="")), patch.object(
|
||||
main, "_identity_system_prompt", new=AsyncMock(return_value="Du bist JARVIS.")
|
||||
):
|
||||
text, output_tokens, total_tokens = await main.run_chat_completion(
|
||||
[{"role": "user", "content": "Verschiebe den Termin X"}], conversation_id=1
|
||||
)
|
||||
|
|
@ -136,7 +140,7 @@ async def test_run_chat_completion_lists_recent_emails():
|
|||
|
||||
with patch.object(main, "list_recent_emails", new=AsyncMock(return_value=[])), patch.object(
|
||||
main, "build_memory_context", new=AsyncMock(return_value="")
|
||||
):
|
||||
), patch.object(main, "_identity_system_prompt", new=AsyncMock(return_value="Du bist JARVIS.")):
|
||||
text, output_tokens, total_tokens = await main.run_chat_completion(
|
||||
[{"role": "user", "content": "Was ist neu im Postfach?"}], conversation_id=1
|
||||
)
|
||||
|
|
@ -168,7 +172,7 @@ async def test_run_chat_completion_includes_current_datetime_in_system_prompt():
|
|||
|
||||
with patch.object(main, "build_memory_context", new=AsyncMock(return_value="")), patch.object(
|
||||
main, "_current_datetime_context", return_value="Aktuelles Datum und Uhrzeit: TESTMARKER"
|
||||
):
|
||||
), patch.object(main, "_identity_system_prompt", new=AsyncMock(return_value="Du bist JARVIS.")):
|
||||
await main.run_chat_completion([{"role": "user", "content": "Hi"}], conversation_id=1)
|
||||
|
||||
_, kwargs = main.claude_client.messages.create.call_args
|
||||
|
|
|
|||
|
|
@ -206,7 +206,7 @@ async def test_run_chat_completion_includes_memory_context_in_system_prompt():
|
|||
|
||||
with patch.object(
|
||||
main, "build_memory_context", new=AsyncMock(return_value="Bekannte Fakten ueber den Nutzer:\n- Hund heisst Bruno")
|
||||
):
|
||||
), patch.object(main, "_identity_system_prompt", new=AsyncMock(return_value="Du bist JARVIS.")):
|
||||
await main.run_chat_completion([{"role": "user", "content": "Wie geht es meinem Hund?"}], conversation_id=1)
|
||||
|
||||
_, kwargs = main.claude_client.messages.create.call_args
|
||||
|
|
|
|||
|
|
@ -328,7 +328,9 @@ async def test_run_chat_completion_includes_order_tools_and_instructions():
|
|||
main.claude_client = MagicMock()
|
||||
main.claude_client.messages.create.return_value = completion
|
||||
|
||||
with patch.object(main, "build_memory_context", new=AsyncMock(return_value="")):
|
||||
with patch.object(main, "build_memory_context", new=AsyncMock(return_value="")), patch.object(
|
||||
main, "_identity_system_prompt", new=AsyncMock(return_value="Du bist JARVIS.")
|
||||
):
|
||||
await main.run_chat_completion(
|
||||
[{"role": "user", "content": "Neue Bestellung fuer Feuerwehr Onza"}], conversation_id=1
|
||||
)
|
||||
|
|
|
|||
|
|
@ -113,3 +113,14 @@ def test_put_settings_endpoint_rejects_unknown_key(client):
|
|||
def test_put_settings_endpoint_requires_admin_key(client):
|
||||
response = client.put("/api/v1/settings", json={"assistant_name": "X"})
|
||||
assert response.status_code == 401
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_identity_system_prompt_uses_settings():
|
||||
settings = {"assistant_name": "FRIDAY", "company_name": "Stark Industries", "contact_email": "info@stark.example"}
|
||||
with patch.object(main, "get_all_settings", new=AsyncMock(return_value=settings)):
|
||||
prompt = await main._identity_system_prompt()
|
||||
|
||||
assert "FRIDAY" in prompt
|
||||
assert "Stark Industries" in prompt
|
||||
assert "info@stark.example" in prompt
|
||||
|
|
|
|||
Loading…
Reference in New Issue