Docs/installation tutorial (#7)

* [add]修改迁移文件新建空白表结构

* Add installation guide and environment setup

Added installation instructions and environment requirements for MemoryBear.

* [delete]删除api,web的readme.md。只保留唯一readme.md

* Fix database connection example in README

Update database connection configuration example in README.
This commit is contained in:
lanceyq
2025-12-05 21:38:31 +08:00
committed by GitHub
parent 9d1c546173
commit 570392aa6f
17 changed files with 324 additions and 254 deletions

View File

@@ -1,124 +0,0 @@
# Memory Bear 前端项目
## 快速开始
### 环境要求
- Python 3.12
- PostgreSQL 13+
- Neo4j 4.4+
- Redis 6.0+
### 安装依赖
```bash
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
# 方式一:基于 pyproject 安装
pip install .
# 方式二:使用 requirements.txt
pip install -r requirements.txt
```
### 配置环境变量
创建 `.env` 文件(示例):
```env
# Postgres
DB_HOST=127.0.0.1
DB_PORT=5432
DB_USER=postgres
DB_PASSWORD=your-password
DB_NAME=redbear-mem
DB_AUTO_UPGRADE=false
# Neo4j
NEO4J_URI=bolt://localhost:7687
NEO4J_USERNAME=neo4j
NEO4J_PASSWORD=your-password
# Redis
REDIS_HOST=127.0.0.1
REDIS_PORT=6379
REDIS_DB=1
# LLM / API Keys按需
OPENAI_API_KEY=your-openai-key
DASHSCOPE_API_KEY=your-dashscope-key
# 其他
WEB_URL=http://localhost:3000
LOG_LEVEL=INFO
```
### 初始化与启动
```bash
# 如需自动迁移数据库:设置 DB_AUTO_UPGRADE=true 或手动执行
alembic upgrade head
# 激活虚拟环境
api\.venv\Scripts\activate
# 目录切换到api下
cd api
# 启动开发服务
uvicorn app.main:app --reload --port 8000
# 打开交互文档
# http://localhost:8000/docs
```
## 项目结构
```
app/
├── main.py # FastAPI 入口
├── controllers/ # 控制器与路由
├── core/ # 核心:配置、异常、日志等
│ └── memory/ # 记忆模块
│ ├── storage_services/ # 萃取/遗忘/反思/检索
│ ├── agent/ # Agent + MCP 服务
│ ├── utils/ # 工具与提示词
│ └── models/ # 领域模型
└── rag/ # RAG 能力与文档解析
logs/ # 日志与输出
LICENSE # 许可协议Apache-2.0
README.md # 项目说明
```
## API 与路由
- 管理端:`/api`JWT 认证)
- 服务端:`/v1`API Key 认证)
- 根路由健康检查:`GET /` 返回运行状态
- Swagger 文档:`/docs`
## 部署建议
- 使用 `gunicorn` + `uvicorn.workers.UvicornWorker` 作为生产入口
- 配置 `LOG_LEVEL=WARNING` 并启用文件日志
- 数据库与缓存请使用托管服务或独立实例
示例:
```bash
gunicorn app.main:app -w 4 -k uvicorn.workers.UvicornWorker
```
## 许可证
本项目采用 Apache License 2.0 开源协议,详情见 `LICENSE`
## 致谢与交流
- 问题反馈与讨论:请提交 Issue 到代码仓库
- 欢迎贡献:提交 PR 前请先创建功能分支并遵循常规提交信息格式
- 如感兴趣需要联络tianyou_hubm@redbearai.com

View File

@@ -14,7 +14,7 @@ DB_NAME=
# Database Migration Configuration
# Set to true to automatically upgrade database schema on startup
DB_AUTO_UPGRADE=false
DB_AUTO_UPGRADE=true

View File

@@ -35,7 +35,7 @@ def upgrade() -> None:
sa.PrimaryKeyConstraint('id')
)
op.create_index(op.f('ix_app_shares_id'), 'app_shares', ['id'], unique=False)
op.drop_table('data_config')
op.execute('DROP TABLE IF EXISTS data_config')
op.add_column('conversations', sa.Column('workspace_id', sa.UUID(), nullable=False, comment='工作空间ID'))
op.create_foreign_key(None, 'conversations', 'workspaces', ['workspace_id'], ['id'])
# ### end Alembic commands ###

View File

@@ -47,7 +47,7 @@ def upgrade() -> None:
sa.PrimaryKeyConstraint('id')
)
op.create_index(op.f('ix_messages_id'), 'messages', ['id'], unique=False)
op.drop_table('data_config')
op.execute('DROP TABLE IF EXISTS data_config')
# ### end Alembic commands ###

View File

@@ -20,11 +20,31 @@ depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('data_config', sa.Column('llm', sa.String(), nullable=True, comment='LLM模型配置ID'))
# 检查表是否存在再添加列
op.execute("""
DO $$
BEGIN
IF EXISTS (SELECT FROM information_schema.tables WHERE table_name = 'data_config')
AND NOT EXISTS (SELECT FROM information_schema.columns
WHERE table_name = 'data_config' AND column_name = 'llm') THEN
ALTER TABLE data_config ADD COLUMN llm VARCHAR;
COMMENT ON COLUMN data_config.llm IS 'LLM模型配置ID';
END IF;
END $$;
""")
# ### end Alembic commands ###
def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column('data_config', 'llm')
# 检查列是否存在再删除
op.execute("""
DO $$
BEGIN
IF EXISTS (SELECT FROM information_schema.columns
WHERE table_name = 'data_config' AND column_name = 'llm') THEN
ALTER TABLE data_config DROP COLUMN llm;
END IF;
END $$;
""")
# ### end Alembic commands ###

View File

@@ -20,14 +20,21 @@ depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.alter_column('data_config', 'llm_id',
existing_type=sa.VARCHAR(),
comment='LLM模型配置ID',
existing_nullable=True)
op.alter_column('data_config', 'embedding_id',
existing_type=sa.VARCHAR(),
comment='嵌入模型配置ID',
existing_nullable=True)
# 检查表和列是否存在再进行操作
op.execute("""
DO $$
BEGIN
IF EXISTS (SELECT FROM information_schema.columns
WHERE table_name = 'data_config' AND column_name = 'llm_id') THEN
COMMENT ON COLUMN data_config.llm_id IS 'LLM模型配置ID';
END IF;
IF EXISTS (SELECT FROM information_schema.columns
WHERE table_name = 'data_config' AND column_name = 'embedding_id') THEN
COMMENT ON COLUMN data_config.embedding_id IS '嵌入模型配置ID';
END IF;
END $$;
""")
op.add_column('workspaces', sa.Column('storage_type', sa.String(), nullable=True))
# ### end Alembic commands ###

View File

@@ -20,8 +20,9 @@ depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_table('data_config_copy1')
op.drop_table('data_config')
# 使用 IF EXISTS 避免表不存在时报错
op.execute('DROP TABLE IF EXISTS data_config_copy1')
op.execute('DROP TABLE IF EXISTS data_config')
op.add_column('agent_configs', sa.Column('model_parameters', postgresql.JSON(astext_type=sa.Text()), nullable=True, comment='模型参数配置temperature、max_tokens等'))
# ### end Alembic commands ###

View File

@@ -20,7 +20,7 @@ depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_table('data_config')
op.execute('DROP TABLE IF EXISTS data_config')
op.add_column('app_releases', sa.Column('release_notes', sa.String(), nullable=True, comment='版本说明'))
# ### end Alembic commands ###

View File

@@ -358,8 +358,9 @@ def upgrade() -> None:
$$ LANGUAGE plpgsql;
""")
# 创建 documents 表上的触发器
# 创建 documents 表上的触发器(如果不存在)
op.execute("""
DROP TRIGGER IF EXISTS tr_documents_update_stats ON documents;
CREATE TRIGGER tr_documents_update_stats
AFTER INSERT OR UPDATE OR DELETE ON documents
FOR EACH ROW

View File

@@ -69,8 +69,9 @@ def upgrade():
$$ LANGUAGE plpgsql;
""")
# 创建 documents 表上的触发器
# 创建 documents 表上的触发器(如果不存在)
op.execute("""
DROP TRIGGER IF EXISTS tr_documents_update_stats ON documents;
CREATE TRIGGER tr_documents_update_stats
AFTER INSERT OR UPDATE OR DELETE ON documents
FOR EACH ROW

View File

@@ -184,5 +184,5 @@ def downgrade() -> None:
op.drop_table('end_users')
op.drop_index(op.f('ix_retrieval_info_id'), table_name='retrieval_info')
op.drop_table('retrieval_info')
op.drop_table('data_config')
op.execute('DROP TABLE IF EXISTS data_config')
# ### end Alembic commands ###

View File

@@ -24,12 +24,22 @@ def upgrade() -> None:
# 先删除依赖的视图(如果存在)
op.execute("DROP VIEW IF EXISTS data_config_sorted CASCADE")
op.alter_column('data_config', 'llm_id',
existing_type=sa.VARCHAR(),
comment='LLM模型配置ID',
existing_comment='临时',
existing_nullable=True)
op.drop_column('data_config', 'llm')
# 检查表和列是否存在再进行操作
op.execute("""
DO $$
BEGIN
IF EXISTS (SELECT FROM information_schema.columns
WHERE table_name = 'data_config' AND column_name = 'llm_id') THEN
ALTER TABLE data_config ALTER COLUMN llm_id SET DATA TYPE VARCHAR;
COMMENT ON COLUMN data_config.llm_id IS 'LLM模型配置ID';
END IF;
IF EXISTS (SELECT FROM information_schema.columns
WHERE table_name = 'data_config' AND column_name = 'llm') THEN
ALTER TABLE data_config DROP COLUMN llm;
END IF;
END $$;
""")
# ### end Alembic commands ###

View File

@@ -20,19 +20,29 @@ depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.alter_column('data_config', 'workspace_id',
existing_type=sa.UUID(),
comment='工作空间ID',
existing_comment='comment',
existing_nullable=True)
# 检查列是否存在再进行操作
op.execute("""
DO $$
BEGIN
IF EXISTS (SELECT FROM information_schema.columns
WHERE table_name = 'data_config' AND column_name = 'workspace_id') THEN
COMMENT ON COLUMN data_config.workspace_id IS '工作空间ID';
END IF;
END $$;
""")
# ### end Alembic commands ###
def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.alter_column('data_config', 'workspace_id',
existing_type=sa.UUID(),
comment='comment',
existing_comment='工作空间ID',
existing_nullable=True)
# 检查列是否存在再进行操作
op.execute("""
DO $$
BEGIN
IF EXISTS (SELECT FROM information_schema.columns
WHERE table_name = 'data_config' AND column_name = 'workspace_id') THEN
COMMENT ON COLUMN data_config.workspace_id IS 'comment';
END IF;
END $$;
""")
# ### end Alembic commands ###

View File

@@ -20,8 +20,9 @@ depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_table('mappings_copy1')
op.drop_table('mappings')
# 使用 IF EXISTS 避免表不存在时报错
op.execute('DROP TABLE IF EXISTS mappings_copy1')
op.execute('DROP TABLE IF EXISTS mappings')
op.add_column('agent_configs', sa.Column('knowledge_retrieval', postgresql.JSON(astext_type=sa.Text()), nullable=True, comment='知识库检索配置'))
op.add_column('agent_configs', sa.Column('memory', postgresql.JSON(astext_type=sa.Text()), nullable=True, comment='记忆配置'))
op.add_column('agent_configs', sa.Column('variables', postgresql.JSON(astext_type=sa.Text()), nullable=True, comment='变量配置'))