Skip to content

Commit 45f3d01

Browse files
committed
fix (memory): logging for memory server
1 parent 171cd31 commit 45f3d01

5 files changed

Lines changed: 27 additions & 36 deletions

File tree

src/server/mcp_hub/memory/auth.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import logging
21
from fastmcp import Context
32
from fastmcp.exceptions import ToolError
3+
from fastmcp.utilities.logging import get_logger
44

5-
logger = logging.getLogger(__name__)
5+
logger = get_logger(__name__)
66

77
def get_user_id_from_context(ctx: Context) -> str:
88
"""

src/server/mcp_hub/memory/db.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import os
2-
import logging
32
import asyncpg
43
import asyncio
54
from dotenv import load_dotenv
65
from typing import Dict
76

7+
from fastmcp.utilities.logging import get_logger
88
from .constants import TOPICS
99

1010
# Load .env file for 'dev-local' environment.
@@ -14,7 +14,7 @@
1414
if os.path.exists(dotenv_path):
1515
load_dotenv(dotenv_path=dotenv_path)
1616

17-
logger = logging.getLogger(__name__)
17+
logger = get_logger(__name__)
1818

1919
# PostgreSQL connection details
2020
POSTGRES_USER = os.getenv("POSTGRES_USER")

src/server/mcp_hub/memory/llm.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
11
import os
2-
import logging
32
from qwen_agent.agents import Assistant
43
from typing import Dict, Any
54
import json
65

76
from . import prompts
7+
from main.llm import run_agent_with_fallback
8+
from fastmcp.utilities.logging import get_logger
9+
10+
logger = get_logger(__name__)
811

912
# Use the main server's LLM config
1013
OPENAI_API_BASE_URL = os.getenv("OPENAI_API_BASE_URL", "http://localhost:11434/v1/") # Keep for consistency in config
1114
OPENAI_MODEL_NAME = os.getenv("OPENAI_MODEL_NAME", "qwen3:4b")
1215
OPENAI_API_KEYS = [key for key in [os.getenv("OPENAI_API_KEY"), os.getenv("OPENAI_API_KEY_FALLBACK_1"), os.getenv("OPENAI_API_KEY_FALLBACK_2")] if key]
1316

14-
logger = logging.getLogger(__name__)
15-
1617
def _get_base_llm_config() -> Dict[str, Any]:
1718
config = {
1819
'model': OPENAI_MODEL_NAME,
@@ -55,9 +56,6 @@ def run_agent_with_prompt(agent_config: Dict[str, Any], user_prompt: str) -> str
5556
messages = [{'role': 'user', 'content': user_prompt}]
5657
final_content = ""
5758

58-
# Import here to avoid circular dependency issues at module load time
59-
from main.llm import run_agent_with_fallback
60-
6159
try:
6260
for chunk in run_agent_with_fallback(system_message=system_message, function_list=[], messages=messages):
6361
if isinstance(chunk, list) and chunk and chunk[-1].get("role") == "assistant":

src/server/mcp_hub/memory/main.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import os
2-
import logging
32
import asyncio
43
from typing import Dict, Any, List
54
from contextlib import asynccontextmanager
65
from workers.tasks import cud_memory_task
76

87
from dotenv import load_dotenv
98
from fastmcp import FastMCP, Context
9+
from fastmcp.utilities.logging import configure_logging, get_logger
1010

1111
from . import auth, utils, db
1212

@@ -17,8 +17,9 @@
1717
if os.path.exists(dotenv_path):
1818
load_dotenv(dotenv_path=dotenv_path)
1919

20-
logging.basicConfig(level=logging.INFO)
21-
logger = logging.getLogger(__name__)
20+
# --- Standardized Logging Setup ---
21+
configure_logging(level="INFO")
22+
logger = get_logger(__name__)
2223

2324
# --- MCP Server Initialization ---
2425
@asynccontextmanager
@@ -116,5 +117,5 @@ async def delete_memory_by_source(ctx: Context, source_name: str) -> Dict[str, A
116117
host = os.getenv("MCP_SERVER_HOST", "127.0.0.1")
117118
port = int(os.getenv("MCP_SERVER_PORT", 8001))
118119

119-
print(f"Starting Memory MCP Server on http://{host}:{port}")
120+
logger.info(f"Starting Memory MCP Server on http://{host}:{port}")
120121
mcp.run(transport="sse", host=host, port=port)

src/server/mcp_hub/memory/utils.py

Lines changed: 14 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,19 @@
11
import os
22
import json
3-
import logging
43
import re
54
from datetime import datetime, timedelta, timezone
65
from typing import Dict, Any, List, Optional
76

87
import numpy as np
98
import google.generativeai as genai
109
from pgvector.asyncpg import register_vector
10+
from fastmcp.utilities.logging import get_logger
1111

1212
from . import db, llm
13-
from .prompts import (
14-
fact_relevance_user_prompt_template,
15-
fact_summarization_user_prompt_template,
16-
fact_extraction_user_prompt_template,
17-
cud_decision_user_prompt_template,
18-
fact_analysis_user_prompt_template,
19-
)
13+
from .prompts import fact_analysis_user_prompt_template
14+
from main.config import EMBEDDING_MODEL_NAME, GEMINI_API_KEY
2015

21-
logging.basicConfig(level=logging.INFO)
22-
logger = logging.getLogger(__name__)
16+
logger = get_logger(__name__)
2317

2418
# --- Module-level state (initialized by lifespan event) ---
2519
embed_model_name: str = None
@@ -29,13 +23,11 @@
2923
def initialize_embedding_model():
3024
global embed_model_name
3125
if embed_model_name is None:
32-
model_name = os.getenv("EMBEDDING_MODEL_NAME", "models/gemini-embedding-001")
33-
api_key = os.getenv("GEMINI_API_KEY")
34-
if not api_key:
35-
raise ValueError("GEMINI_API_KEY environment variable not set.")
36-
logger.info(f"Initializing embedding model: {model_name}")
37-
genai.configure(api_key=api_key)
38-
embed_model_name = model_name
26+
if not GEMINI_API_KEY:
27+
raise ValueError("GEMINI_API_KEY is not set in main.config.")
28+
logger.info(f"Initializing embedding model: {EMBEDDING_MODEL_NAME}")
29+
genai.configure(api_key=GEMINI_API_KEY)
30+
embed_model_name = EMBEDDING_MODEL_NAME
3931

4032
def initialize_agents():
4133
global agents
@@ -129,7 +121,7 @@ def _get_normalized_embedding(text: str, task_type: str) -> np.ndarray:
129121

130122
async def search_memory(user_id: str, query: str) -> str: # noqa: E501
131123
"""Searches memory by performing a semantic search, filtering for relevance, and summarizing results."""
132-
print(f"Executing search_memory for user_id='{user_id}' with query: '{query}'")
124+
logger.info(f"Executing search_memory for user_id='{user_id}' with query: '{query}'")
133125
pool = await db.get_db_pool()
134126
async with pool.acquire() as conn:
135127
await register_vector(conn)
@@ -148,7 +140,7 @@ async def search_memory(user_id: str, query: str) -> str: # noqa: E501
148140
)
149141

150142
found_facts = [r['content'] for r in records]
151-
print(f"Found {found_facts} potentially relevant facts from vector search.")
143+
logger.info(f"Found {len(found_facts)} potentially relevant facts from vector search.")
152144

153145
if not found_facts:
154146
logger.info("No facts found from vector search. Returning.")
@@ -170,10 +162,10 @@ async def search_memory(user_id: str, query: str) -> str: # noqa: E501
170162
except (json.JSONDecodeError, AttributeError):
171163
logger.warning(f"Could not parse relevance check response: {relevance_raw}")
172164

173-
print(f"Step 3/4: Found {relevant_facts} truly relevant facts after filtering.")
165+
logger.info(f"Step 3/4: Found {len(relevant_facts)} truly relevant facts after filtering.")
174166

175167
if not relevant_facts:
176-
print("No relevant facts remained after filtering. Returning message to user.")
168+
logger.info("No relevant facts remained after filtering. Returning message to user.")
177169
return "No relevant information found in your memory."
178170

179171
# Step 4: Summarization
@@ -182,7 +174,7 @@ async def search_memory(user_id: str, query: str) -> str: # noqa: E501
182174
summary_raw = llm.run_agent_with_prompt(agents["fact_summarization"], prompt)
183175
summary = clean_llm_output(summary_raw)
184176

185-
print(f"Summary generated: {summary}")
177+
logger.info(f"Summary generated: {summary[:100]}...")
186178

187179
logger.info("Search complete. Returning summary.")
188180
return summary if isinstance(summary, str) and summary else "Could not generate a summary from the retrieved information."

0 commit comments

Comments
 (0)