liurenchaxin/tools/memory_bank/memory_bank_web_interface.py

299 lines
11 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
"""
Vertex AI Memory Bank Web界面
一个简单的Streamlit应用用于通过Web界面访问和管理Memory Bank
"""
import streamlit as st
import asyncio
import sys
import os
from datetime import datetime
# 添加项目路径
sys.path.append('/Users/ben/liurenchaxin/src')
try:
from jixia.memory.factory import get_memory_backend
except ImportError as e:
st.error(f"无法导入jixia模块: {e}")
st.info("请确保已激活虚拟环境并安装了所需依赖")
st.stop()
# 页面配置
st.set_page_config(
page_title="Memory Bank 管理界面",
page_icon="🧠",
layout="wide"
)
# 标题
st.title("🧠 Vertex AI Memory Bank 管理界面")
st.markdown("---")
# 侧边栏配置
st.sidebar.header("配置")
project_id = st.sidebar.text_input("项目ID", value="inner-radius-469712-e9")
location = st.sidebar.text_input("区域", value="us-central1")
# 八仙列表
EIGHT_IMMORTALS = [
"lvdongbin", "tieguaili", "hanxiangzi", "lanzaihe",
"hesengu", "zhonghanli", "caogujiu", "hanzhongli"
]
# 缓存Memory Bank后端
@st.cache_resource
def get_memory_backend_cached():
"""获取Memory Bank后端缓存"""
try:
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
backend = loop.run_until_complete(get_memory_backend("vertex"))
return backend, loop
except Exception as e:
st.error(f"初始化Memory Bank失败: {e}")
return None, None
# 异步函数包装器
def run_async(coro):
"""运行异步函数"""
backend, loop = get_memory_backend_cached()
if backend is None:
return None
try:
return loop.run_until_complete(coro)
except Exception as e:
st.error(f"操作失败: {e}")
return None
# 主界面
tab1, tab2, tab3, tab4 = st.tabs(["📋 Memory Bank列表", "🔍 搜索记忆", " 添加记忆", "📊 统计信息"])
with tab1:
st.header("Memory Bank 实例列表")
if st.button("🔄 刷新列表", key="refresh_list"):
st.rerun()
# 显示八仙Memory Bank状态
cols = st.columns(4)
for i, immortal in enumerate(EIGHT_IMMORTALS):
with cols[i % 4]:
with st.container():
st.subheader(f"🧙‍♂️ {immortal}")
# 检查Memory Bank状态
backend, _ = get_memory_backend_cached()
if backend:
try:
# 尝试获取agent context来验证Memory Bank存在
context = run_async(backend.get_agent_context(immortal))
if context is not None:
st.success("✅ 活跃")
# 显示记忆数量
memories = run_async(backend.search_memories(immortal, "", limit=100))
if memories:
st.info(f"📝 记忆数量: {len(memories)}")
else:
st.info("📝 记忆数量: 0")
else:
st.warning("⚠️ 未初始化")
except Exception as e:
st.error(f"❌ 错误: {str(e)[:50]}...")
else:
st.error("❌ 连接失败")
with tab2:
st.header("🔍 搜索记忆")
col1, col2 = st.columns([1, 2])
with col1:
selected_agent = st.selectbox("选择Agent", EIGHT_IMMORTALS, key="search_agent")
search_query = st.text_input("搜索关键词", placeholder="输入要搜索的内容...", key="search_query")
search_limit = st.slider("结果数量", 1, 50, 10, key="search_limit")
if st.button("🔍 搜索", key="search_button"):
if search_query:
with st.spinner("搜索中..."):
backend, _ = get_memory_backend_cached()
if backend:
memories = run_async(backend.search_memories(selected_agent, search_query, limit=search_limit))
st.session_state['search_results'] = memories
st.session_state['search_agent'] = selected_agent
st.session_state['search_query'] = search_query
else:
st.warning("请输入搜索关键词")
with col2:
st.subheader("搜索结果")
if 'search_results' in st.session_state and st.session_state['search_results']:
st.success(f"找到 {len(st.session_state['search_results'])} 条记忆")
for i, memory in enumerate(st.session_state['search_results']):
with st.expander(f"记忆 {i+1}: {memory.get('content', 'N/A')[:50]}..."):
st.write(f"**内容**: {memory.get('content', 'N/A')}")
st.write(f"**类型**: {memory.get('memory_type', 'N/A')}")
st.write(f"**时间**: {memory.get('timestamp', 'N/A')}")
if 'metadata' in memory:
st.write(f"**元数据**: {memory['metadata']}")
elif 'search_results' in st.session_state:
st.info("未找到匹配的记忆")
else:
st.info("请执行搜索以查看结果")
with tab3:
st.header(" 添加记忆")
col1, col2 = st.columns([1, 1])
with col1:
add_agent = st.selectbox("选择Agent", EIGHT_IMMORTALS, key="add_agent")
memory_type = st.selectbox("记忆类型", ["conversation", "preference", "knowledge", "strategy"], key="memory_type")
memory_content = st.text_area("记忆内容", placeholder="输入要添加的记忆内容...", height=150, key="memory_content")
# 可选的元数据
st.subheader("元数据(可选)")
importance = st.slider("重要性", 1, 10, 5, key="importance")
tags = st.text_input("标签(用逗号分隔)", placeholder="标签1, 标签2, 标签3", key="tags")
if st.button(" 添加记忆", key="add_memory_button"):
if memory_content:
with st.spinner("添加记忆中..."):
backend, _ = get_memory_backend_cached()
if backend:
# 准备元数据
metadata = {
"importance": importance,
"timestamp": datetime.now().isoformat(),
"source": "web_interface"
}
if tags:
metadata["tags"] = [tag.strip() for tag in tags.split(",")]
# 添加记忆
success = run_async(backend.add_memory(
agent_id=add_agent,
content=memory_content,
memory_type=memory_type,
metadata=metadata
))
if success:
st.success("✅ 记忆添加成功!")
# 清空输入
st.session_state['memory_content'] = ""
st.session_state['tags'] = ""
else:
st.error("❌ 添加记忆失败")
else:
st.warning("请输入记忆内容")
with col2:
st.subheader("添加记忆预览")
if memory_content:
st.info(f"**Agent**: {add_agent}")
st.info(f"**类型**: {memory_type}")
st.info(f"**内容**: {memory_content}")
st.info(f"**重要性**: {importance}/10")
if tags:
st.info(f"**标签**: {tags}")
else:
st.info("输入记忆内容以查看预览")
with tab4:
st.header("📊 统计信息")
if st.button("🔄 刷新统计", key="refresh_stats"):
st.rerun()
# 获取统计信息
backend, _ = get_memory_backend_cached()
if backend:
stats_data = []
for immortal in EIGHT_IMMORTALS:
try:
# 获取记忆数量
memories = run_async(backend.search_memories(immortal, "", limit=1000))
memory_count = len(memories) if memories else 0
# 获取agent context
context = run_async(backend.get_agent_context(immortal))
status = "活跃" if context else "未初始化"
stats_data.append({
"Agent": immortal,
"状态": status,
"记忆数量": memory_count,
"最后更新": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
})
except Exception as e:
stats_data.append({
"Agent": immortal,
"状态": "错误",
"记忆数量": 0,
"最后更新": f"错误: {str(e)[:30]}..."
})
# 显示统计表格
st.dataframe(stats_data, use_container_width=True)
# 显示汇总信息
col1, col2, col3, col4 = st.columns(4)
total_agents = len(EIGHT_IMMORTALS)
active_agents = sum(1 for item in stats_data if item["状态"] == "活跃")
total_memories = sum(item["记忆数量"] for item in stats_data)
avg_memories = total_memories / total_agents if total_agents > 0 else 0
with col1:
st.metric("总Agent数", total_agents)
with col2:
st.metric("活跃Agent数", active_agents)
with col3:
st.metric("总记忆数", total_memories)
with col4:
st.metric("平均记忆数", f"{avg_memories:.1f}")
# 页脚
st.markdown("---")
st.markdown(
"""
<div style='text-align: center; color: #666;'>
🧠 Vertex AI Memory Bank Web界面 |
<a href='https://cloud.google.com/vertex-ai/generative-ai/docs/agent-engine/memory-bank/overview' target='_blank'>官方文档</a>
</div>
""",
unsafe_allow_html=True
)
# 使用说明
with st.expander("📖 使用说明"):
st.markdown("""
### 功能说明
1. **Memory Bank列表**: 查看所有八仙角色的Memory Bank状态和记忆数量
2. **搜索记忆**: 在指定Agent的记忆中搜索特定内容
3. **添加记忆**: 为Agent添加新的记忆支持不同类型和元数据
4. **统计信息**: 查看所有Agent的统计数据和汇总信息
### 使用前准备
1. 确保已激活虚拟环境: `source venv/bin/activate`
2. 确保已设置Google Cloud认证: `gcloud auth application-default login`
3. 运行此界面: `streamlit run memory_bank_web_interface.py`
### 注意事项
- Memory Bank目前仅在us-central1区域可用
- 搜索功能支持模糊匹配
- 添加的记忆会立即生效
- 统计信息实时更新
""")