fix(mcp): add back bank list and create_bank tools (#123)
* fix(mcp): add back bank list and create_bank tools * fix tests * fix tests
This commit is contained in:
parent
c65c6a9dc0
commit
9fd567984c
3 changed files with 105 additions and 24 deletions
|
|
@ -187,6 +187,60 @@ def create_mcp_server(memory: MemoryEngine) -> FastMCP:
|
|||
logger.error(f"Error reflecting: {e}", exc_info=True)
|
||||
return f'{{"error": "{e}", "text": ""}}'
|
||||
|
||||
@mcp.tool()
|
||||
async def list_banks() -> str:
|
||||
"""
|
||||
List all available memory banks.
|
||||
|
||||
Use this tool to discover what memory banks exist in the system.
|
||||
Each bank is an isolated memory store (like a separate "brain").
|
||||
|
||||
Returns:
|
||||
JSON list of banks with their IDs, names, dispositions, and backgrounds.
|
||||
"""
|
||||
try:
|
||||
banks = await memory.list_banks(request_context=RequestContext())
|
||||
return json.dumps({"banks": banks}, indent=2)
|
||||
except Exception as e:
|
||||
logger.error(f"Error listing banks: {e}", exc_info=True)
|
||||
return f'{{"error": "{e}", "banks": []}}'
|
||||
|
||||
@mcp.tool()
|
||||
async def create_bank(bank_id: str, name: str | None = None, background: str | None = None) -> str:
|
||||
"""
|
||||
Create a new memory bank or get an existing one.
|
||||
|
||||
Memory banks are isolated stores - each one is like a separate "brain" for a user/agent.
|
||||
Banks are auto-created with default settings if they don't exist.
|
||||
|
||||
Args:
|
||||
bank_id: Unique identifier for the bank (e.g., 'user-123', 'agent-alpha')
|
||||
name: Optional human-friendly name for the bank
|
||||
background: Optional background context about the bank's owner/purpose
|
||||
"""
|
||||
try:
|
||||
# get_bank_profile auto-creates bank if it doesn't exist
|
||||
profile = await memory.get_bank_profile(bank_id, request_context=RequestContext())
|
||||
|
||||
# Update name/background if provided
|
||||
if name is not None or background is not None:
|
||||
await memory.update_bank(
|
||||
bank_id,
|
||||
name=name,
|
||||
background=background,
|
||||
request_context=RequestContext(),
|
||||
)
|
||||
# Fetch updated profile
|
||||
profile = await memory.get_bank_profile(bank_id, request_context=RequestContext())
|
||||
|
||||
# Serialize disposition if it's a Pydantic model
|
||||
if "disposition" in profile and hasattr(profile["disposition"], "model_dump"):
|
||||
profile["disposition"] = profile["disposition"].model_dump()
|
||||
return json.dumps(profile, indent=2)
|
||||
except Exception as e:
|
||||
logger.error(f"Error creating bank: {e}", exc_info=True)
|
||||
return f'{{"error": "{e}"}}'
|
||||
|
||||
return mcp
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ def mock_memory():
|
|||
"""Create a mock MemoryEngine."""
|
||||
memory = MagicMock()
|
||||
memory.retain_batch_async = AsyncMock()
|
||||
memory.submit_async_retain = AsyncMock(return_value={"operation_id": "test-op-123"})
|
||||
memory.recall_async = AsyncMock(return_value=MagicMock(results=[]))
|
||||
return memory
|
||||
|
||||
|
|
@ -44,11 +45,11 @@ async def test_mcp_tools_use_context_bank_id(mock_memory):
|
|||
assert "retain" in tools
|
||||
assert "recall" in tools
|
||||
|
||||
# Test retain with bank_id from context
|
||||
# Test retain with bank_id from context (use async_processing=False for synchronous test)
|
||||
token = _current_bank_id.set("context-bank-id")
|
||||
try:
|
||||
retain_tool = tools["retain"]
|
||||
result = await retain_tool.fn(content="test content", context="test_context")
|
||||
result = await retain_tool.fn(content="test content", context="test_context", async_processing=False)
|
||||
assert "successfully" in result.lower()
|
||||
|
||||
# Verify the memory was called with the context bank_id
|
||||
|
|
|
|||
|
|
@ -137,42 +137,68 @@ hindsight.retain(
|
|||
|
||||
## Supported Languages
|
||||
|
||||
Hindsight supports any language that your configured LLM can understand. This typically includes:
|
||||
**Hindsight's multilingual support depends entirely on your LLM's language capabilities.** Hindsight instructs the LLM to detect the input language and respond in that same language. If your LLM supports a language, Hindsight will work with it.
|
||||
|
||||
| Language | Script | Example |
|
||||
|----------|--------|---------|
|
||||
| Chinese (Simplified) | 简体中文 | 张伟是软件工程师 |
|
||||
| Chinese (Traditional) | 繁體中文 | 張偉是軟體工程師 |
|
||||
| Japanese | 日本語 | 田中さんはエンジニアです |
|
||||
| Korean | 한국어 | 김철수는 개발자입니다 |
|
||||
| Arabic | العربية | أحمد مهندس برمجيات |
|
||||
| Russian | Русский | Иван - разработчик |
|
||||
| Spanish | Español | María es ingeniera |
|
||||
| French | Français | Pierre est développeur |
|
||||
| German | Deutsch | Hans ist Entwickler |
|
||||
| And many more... | | |
|
||||
Most modern LLMs (GPT-4, Claude, Gemini, Llama 3, etc.) support dozens of languages including:
|
||||
|
||||
The actual language support depends on your LLM provider's capabilities.
|
||||
- **East Asian**: Chinese (Simplified/Traditional), Japanese, Korean
|
||||
- **European**: Spanish, French, German, Italian, Portuguese, Dutch, Polish, Russian
|
||||
- **Middle Eastern**: Arabic, Hebrew, Turkish
|
||||
- **South Asian**: Hindi, Bengali, Tamil
|
||||
- **Southeast Asian**: Thai, Vietnamese, Indonesian
|
||||
|
||||
**To verify support for your target language**, test your LLM directly with content in that language. If the LLM can understand and generate text in the language, Hindsight will preserve it correctly.
|
||||
|
||||
---
|
||||
|
||||
## Best Practices
|
||||
## Configuring for Multilingual Use
|
||||
|
||||
### 1. Keep Content in One Language Per Retain Call
|
||||
While mixed content works, keeping each `retain` call in a single language produces more consistent results.
|
||||
For optimal multilingual performance, you should configure all three components of the pipeline:
|
||||
|
||||
### 2. Query in the Same Language as Your Content
|
||||
For best results, query using the same language as your stored content. Cross-language queries (e.g., English query for Chinese content) may work but results can vary.
|
||||
### 1. LLM (Required)
|
||||
Your LLM must support the target languages. Most modern LLMs do, but verify with your specific model.
|
||||
|
||||
### 3. Consider Embedding Model Language Support
|
||||
The default embedding model (`BAAI/bge-small-en-v1.5`) is English-optimized. For better multilingual semantic search, consider using a multilingual embedding model:
|
||||
### 2. Embedding Model (Recommended)
|
||||
The default embedding model (`BAAI/bge-small-en-v1.5`) is **English-only**. For multilingual content, use a multilingual embedding model:
|
||||
|
||||
```bash
|
||||
# In your .env file
|
||||
HINDSIGHT_API_EMBEDDINGS_LOCAL_MODEL=BAAI/bge-m3
|
||||
```
|
||||
|
||||
The `bge-m3` model supports 100+ languages with better cross-lingual retrieval.
|
||||
**Recommended multilingual embedding models:**
|
||||
| Model | Languages | Notes |
|
||||
|-------|-----------|-------|
|
||||
| `BAAI/bge-m3` | 100+ | Best overall multilingual performance |
|
||||
| `intfloat/multilingual-e5-large` | 100+ | Good alternative |
|
||||
| `sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2` | 50+ | Lighter weight |
|
||||
|
||||
### 3. Reranker Model (Recommended)
|
||||
The default reranker (`cross-encoder/ms-marco-MiniLM-L-6-v2`) is **English-only**. For multilingual content, use a multilingual reranker:
|
||||
|
||||
```bash
|
||||
# In your .env file
|
||||
HINDSIGHT_API_RERANKER_LOCAL_MODEL=BAAI/bge-reranker-v2-m3
|
||||
```
|
||||
|
||||
**Recommended multilingual reranker models:**
|
||||
| Model | Languages | Notes |
|
||||
|-------|-----------|-------|
|
||||
| `BAAI/bge-reranker-v2-m3` | 100+ | Best multilingual reranking |
|
||||
| `cross-encoder/mmarco-mMiniLMv2-L12-H384-v1` | 14 | Lighter alternative |
|
||||
|
||||
---
|
||||
|
||||
## Best Practices
|
||||
|
||||
### 1. Use Multilingual Models for Non-English Content
|
||||
If you primarily work with non-English content, configure multilingual embedding and reranker models. English-only models will still store your content correctly, but semantic search quality will be degraded.
|
||||
|
||||
### 2. Keep Content in One Language Per Retain Call
|
||||
While mixed content works, keeping each `retain` call in a single language produces more consistent results.
|
||||
|
||||
### 3. Query in the Same Language as Your Content
|
||||
For best results, query using the same language as your stored content. Cross-language queries (e.g., English query for Chinese content) may work but results can vary depending on your embedding model.
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue