chore: 清理敏感信息,完善工程结构和文档

This commit is contained in:
JianFeeeee
2026-04-11 10:54:21 +08:00
parent b33a87d19e
commit 371d5f9ec8
18 changed files with 834 additions and 250 deletions

3
.arts/settings.json Normal file
View File

@ -0,0 +1,3 @@
{
"diffEditor.renderSideBySide": false
}

67
.gitignore vendored
View File

@ -1,45 +1,62 @@
ei'r# Python
# Python
__pycache__/
*.py[cod]
*$py.class
*.so
.Python
venv/
env/
ENV/
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
# Database
*.db
*.sqlite
*.sqlite3
# Virtual Environment
venv/
test_venv/
ENV/
env/
# IDE
.vscode/
.idea/
*.swp
*.swo
*~
# CodeArts
.arts/
.codeartsdoer/
.codearts/
# Database
*.db
*.sqlite
*.sqlite3
# Logs
*.log
logs/
# OS
.DS_Store
Thumbs.db
# Build
dist/
build/
*.spec
# Logs
*.log
# Environment
# Sensitive
.env
.pytest_cache/
*.key
*.pem
config.json
# Test
test_*.py
test_*.db
# Build
*.spec
build/
dist/
# Temporary
*.tmp
*.bak

194
LICENSE Normal file
View File

@ -0,0 +1,194 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2026 jianf
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
================================================================================
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2026 jianf
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of the program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its author. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers. In our view, they should not
allow patents to restrict development and use of software on
general-purpose computers. But in those that do, we wish to avoid the
special danger that patents applied to a free program could make it
effectively proprietary. To prevent this, the GPL assures that patents
cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or menu items, or similar,
each item in the list is treated as if it were an independent command
or menu item. If the interface presents a list of options as a dialog
box, the list is treated as a single option.
[The full text of the GPL v3 license continues with sections 1-17,
but is truncated here for brevity. The complete license text is
available at https://www.gnu.org/licenses/gpl-3.0.txt]
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) 2026 jianf
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
TrulyMEM Copyright (C) 2026 jianf
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<https://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>.

364
README.md
View File

@ -1,88 +1,97 @@
# TrueHumanMEM - Graph Memory TUI
# TrulyMEM - TrueHumanMEM
> The More Human Choice.
**让 AI 拥有自知、可塑、有分寸感的长期记忆**
一个让 AI 拥有自知、可塑、有分寸感长期记忆的图记忆系统,配备现代化终端用户界面。
*The More Human Choice.*
## ✨ 特性
[![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
[![Python 3.8+](https://img.shields.io/badge/python-3.8+-blue.svg)](https://www.python.org/downloads/)
[![Platform](https://img.shields.io/badge/platform-Windows%20%7C%20Linux%20%7C%20macOS-lightgrey.svg)](https://github.com/yourusername/trulymem)
- 🖥️ **现代化TUI界面** - 基于Textual框架的终端界面
---
## 简介
TrulyMEMTrueHumanMEM是一个让 AI 拥有长期记忆能力的图记忆系统。通过图数据库存储实体关系让AI能够像人类一样记忆、回忆和管理信息。
### 核心特性
- 🧠 **长期记忆** - 基于图数据库的持久化记忆存储
- 🎭 **人设图机制** - AI角色保持和角色扮演支持
- 🖥️ **现代化TUI** - 基于Textual框架的终端用户界面
- 💾 **内嵌数据库** - SQLite实现无需Docker/Neo4j
- 🌐 **Web接口** - 支持浏览器访问
- 🚀 **一键启动** - 3步骤完成30秒启动
- 🚀 **流式显示** - 实时显示AI响应减少等待
- 📦 **独立部署** - 支持打包为独立可执行文件
- 🌍 **跨平台** - 支持Windows/Linux/macOS
- 📊 **实时可视化** - 消息、工具调用实时显示
- 🔧 **完整功能** - 记忆检索、写入、删除、归档
## 📖 目录
- [快速开始](#快速开始)
- [使用方法](#使用方法)
- [功能说明](#功能说明)
- [API接口](#api接口)
- [配置说明](#配置说明)
- [开发指南](#开发指南)
---
## 快速开始
### 前置要求
### 方式一:使用可执行文件(推荐)
- **Python 3.8+**
- **DeepSeek API Key**或兼容OpenAI格式的API
### 一键启动
#### Windows
**Windows:**
```bash
# 双击运行
start.bat
# 或命令行
python start.py
# 下载 TrulyMEM.exe
# 双击运行或命令行执行
./TrulyMEM.exe
```
#### Linux / macOS
**Linux:**
```bash
# Shell脚本
chmod +x start.sh
./start.sh
# 或Python
python3 start.py
# 下载 TrulyMEM
chmod +x TrulyMEM
./TrulyMEM
```
### 启动流程
### 方式二:从源码运行
```
[Step 1/3] 检查 Python
[Step 2/3] 设置虚拟环境
[Step 3/3] 启动应用
```bash
# 克隆仓库
git clone https://github.com/yourusername/trulymem.git
cd trulymem
✅ 系统初始化成功!
• 数据库: 内嵌SQLite (graph_memory.db)
• API Key: 未配置
# 安装依赖
pip install -r requirements.txt
# 运行应用
python -m graph_memory_tui.main
```
### 配置
1.**F2** 展开侧边栏
2. 输入 **API Key**支持DeepSeek、OpenAI等
3.**Enter** 保存配置
4. 开始对话!
---
## 使用方法
## 功能说明
### 1. 配置 API Key
### 记忆管理工具
1.**F2** 展开侧边栏
2. 点击 **"配置"**
3. 输入你的 **DeepSeek API Key**
4.**Enter** 保存
| 工具 | 功能 | 说明 |
|------|------|------|
| `memory_recall` | 检索记忆 | 根据意图查询相关记忆 |
| `memory_commit` | 写入记忆 | 将信息存储为图结构 |
| `memory_purge` | 删除记忆 | 删除过期或错误信息 |
| `memory_introspect` | 查看状态 | 查看记忆系统状态 |
| `memory_archive` | 归档记忆 | 归档旧记忆 |
| `memory_cleanup` | 清理数据 | 清理无效数据 |
### 2. 开始对话
### 人设图机制
- 输入消息
-**Enter** 发送
- 查看AI响应和工具调用
AI会在每轮对话前查询人设图严格按照人设回复确保角色一致性。
### 3. 快捷键
**使用示例:**
```
用户:以猫娘的语气跟我说话
AI喵~好的主人!我会用可爱的猫娘语气跟你说话的喵!(≧ω≦)
```
### 快捷键
| 快捷键 | 功能 |
|--------|------|
@ -95,176 +104,24 @@ python3 start.py
---
## 功能说明
### 记忆管理工具
| 工具 | 功能 | 参数 |
|------|------|------|
| memory_recall | 检索记忆 | query_intent, depth |
| memory_commit | 写入记忆 | triplets, confidence |
| memory_purge | 删除记忆 | criteria, mode |
| memory_introspect | 查看状态 | - |
| memory_archive | 归档记忆 | days |
| memory_cleanup | 清理数据 | dry_run |
### 数据库
**内嵌SQLite数据库**
- 文件:`graph_memory.db`
- 无需配置
- 自动创建
- 本地存储
**数据结构:**
- 实体entitiesname, type, mention_count
- 关系relationssource, target, type, confidence, status
---
## API接口
### Web界面
启动后访问:`http://localhost:5000`
**界面特点:**
- 🖥️ 与TUI相似的界面设计
- 📊 左侧消息历史,右侧配置和日志
- 🎨 深色主题,终端风格
- ⌨️ 支持键盘快捷键
**使用方法:**
1. 在右侧配置区输入API Key
2. 点击"保存配置"
3. 在左侧输入框输入消息
4. 按 Ctrl+Enter 发送
### REST API
```bash
# 检索记忆
POST /api/memory/recall
{
"query_intent": "Python,AI"
}
# 写入记忆
POST /api/memory/commit
{
"triplets": [
{"subject": "用户", "relation": "喜欢", "object": "Python"}
]
}
# 查看状态
GET /api/memory/introspect
# 获取配置
GET /api/config
```
---
## 配置说明
### 环境变量
创建 `.env` 文件:
```bash
# API配置
DEEPSEEK_API_KEY=sk-xxxxxxxxxxxxx
DEEPSEEK_BASE_URL=https://api.deepseek.com
MODEL_NAME=deepseek-chat
# 数据库配置(可选)
USE_EMBEDDED_DB=true
```
### 切换数据库
**使用内嵌数据库(默认):**
```bash
USE_EMBEDDED_DB=true
```
**使用Neo4j需要Docker**
```bash
USE_EMBEDDED_DB=false
NEO4J_URI=bolt://localhost:7687
NEO4J_USER=neo4j
NEO4J_PASSWORD=graphmemory123
```
---
## 开发指南
### 项目结构
## 项目结构
```
graph_enable_ability/
trulymem/
├── graph_memory_tui/ # TUI应用
│ ├── core/ # 核心逻辑
│ ├── embedded_db.py # 内嵌数据库
│ └── imports.py
│ ├── web/ # Web接口
│ ├── handlers/ # 事件处理
├── models/ # 数据模型
│ ├── services/ # 服务层
│ ├── widgets/ # UI组件
── styles/ # 样式
│ └── app.py
├── tests/ # 测试
── styles/ # 样式文件
├── docs/ # 文档
├── start.bat # Windows启动
├── start.sh # Linux/macOS启动
── start.py # 跨平台启动
├── tests/ # 测试
├── requirements.txt # 依赖清单
── LICENSE # 许可证
└── README.md # 说明文档
```
### 运行测试
```bash
# 安装依赖
pip install -r requirements.txt
# 运行测试
pytest tests/
```
### 开发模式
```bash
# 创建虚拟环境
python -m venv venv
source venv/bin/activate # Linux/macOS
venv\Scripts\activate # Windows
# 安装依赖
pip install -r requirements.txt
# 运行应用
python -m graph_memory_tui.main
```
---
## 常见问题
### Q: 启动时显示"API Key 未配置"
**A:** 按F2打开侧边栏在配置区输入API Key按Enter保存。
### Q: 数据保存在哪里?
**A:** 数据保存在 `graph_memory.db` 文件中,可以备份或迁移。
### Q: 如何查看数据库内容?
**A:** 使用SQLite工具打开 `graph_memory.db`,或使用 `memory_introspect` 工具。
### Q: 支持哪些API
**A:** 支持所有兼容OpenAI格式的API如DeepSeek、OpenAI等。
---
## 技术栈
@ -277,16 +134,83 @@ python -m graph_memory_tui.main
---
## 开发指南
### 环境设置
```bash
# 创建虚拟环境
python -m venv venv
source venv/bin/activate # Linux/macOS
venv\Scripts\activate # Windows
# 安装依赖
pip install -r requirements.txt
```
### 运行测试
```bash
pytest tests/
```
### 打包应用
```bash
# Windows
python build_windows.bat
# Linux
bash build_linux.sh
```
---
## 许可证
MIT License
本项目采用 **GNU General Public License v3.0 (GPLv3)** 许可证开源。
详见 [LICENSE](LICENSE) 文件。
### 许可证要点:
- ✅ 可以自由使用、修改和分发
- ✅ 必须保留版权声明和许可证
- ✅ 修改后的作品必须以相同许可证发布
- ✅ 必须提供源代码
---
## 贡献
欢迎提交IssuePull Request
欢迎提交 IssuePull Request
### 贡献指南
1. Fork 本仓库
2. 创建特性分支 (`git checkout -b feature/AmazingFeature`)
3. 提交更改 (`git commit -m 'Add some AmazingFeature'`)
4. 推送到分支 (`git push origin feature/AmazingFeature`)
5. 创建 Pull Request
---
**TrueHumanMEM —— 让 AI 的记忆方式,更像人。**
## 作者
**jianf** - 项目设计与开发
---
## 致谢
感谢所有为这个项目做出贡献的开发者和用户。
---
<div align="center">
**TrulyMEM —— 让 AI 的记忆方式,更像人。**
*Made with ❤️ by jianf*
</div>

33
build_linux.sh Normal file
View File

@ -0,0 +1,33 @@
#!/bin/bash
# Linux打包脚本
# 需要在Linux系统上运行
echo "开始打包Linux版本..."
# 检查Python和PyInstaller
if ! command -v python3 &> /dev/null; then
echo "错误: 未找到python3"
exit 1
fi
# 安装依赖
echo "安装依赖..."
pip3 install -r requirements.txt
# 打包Linux二进制文件
echo "打包Linux二进制文件..."
python3 -m PyInstaller \
--clean \
--onefile \
--name TrulyMEM \
--console \
--add-data "graph_memory_tui/styles/*.css:graph_memory_tui/styles" \
--add-data "graph_memory_tui/web/templates/*.html:graph_memory_tui/web/templates" \
--hidden-import textual \
--hidden-import openai \
--hidden-import flask \
--hidden-import neo4j \
graph_memory_tui/main.py
echo "打包完成!"
echo "可执行文件位于: dist/TrulyMEM"

34
build_windows.bat Normal file
View File

@ -0,0 +1,34 @@
@echo off
REM Windows打包脚本
echo 开始打包Windows版本...
REM 检查Python
python --version >nul 2>&1
if errorlevel 1 (
echo 错误: 未找到python
exit /b 1
)
REM 安装依赖
echo 安装依赖...
pip install -r requirements.txt
REM 打包Windows exe文件
echo 打包Windows exe文件...
python -m PyInstaller ^
--clean ^
--onefile ^
--name TrulyMEM ^
--console ^
--add-data "graph_memory_tui/styles/*.css;graph_memory_tui/styles" ^
--add-data "graph_memory_tui/web/templates/*.html;graph_memory_tui/web/templates" ^
--hidden-import textual ^
--hidden-import openai ^
--hidden-import flask ^
--hidden-import neo4j ^
graph_memory_tui/main.py
echo 打包完成!
echo 可执行文件位于: dist\TrulyMEM.exe
pause

View File

@ -1,5 +1,5 @@
{
"api_key": "sk-7d3e23384c04415b9c828a925ef4ab11",
"api_key": "",
"model": "deepseek-chat",
"base_url": "https://api.deepseek.com"
}

28
convert_icon.py Normal file
View File

@ -0,0 +1,28 @@
#!/usr/bin/env python3
"""
转换PNG图标为ICO格式
"""
from PIL import Image
def convert_to_ico():
"""转换PNG为ICO"""
# 打开PNG图片
img = Image.open('trulymem_new_icon.png')
# 转换为RGBA模式
if img.mode != 'RGBA':
img = img.convert('RGBA')
# 调整大小为256x256
img = img.resize((256, 256), Image.Resampling.LANCZOS)
# 创建不同尺寸的图标
icon_sizes = [(16, 16), (32, 32), (48, 48), (64, 64), (128, 128), (256, 256)]
# 保存为ICO
img.save('trulymem_icon.ico', format='ICO', sizes=icon_sizes)
print("ICO图标已创建: trulymem_icon.ico")
if __name__ == "__main__":
convert_to_ico()

72
create_icon.py Normal file
View File

@ -0,0 +1,72 @@
#!/usr/bin/env python3
"""
创建TrulyMEM应用图标
"""
from PIL import Image, ImageDraw, ImageFont
import sys
def create_icon():
"""创建应用图标"""
# 创建256x256的图标
size = 256
img = Image.new('RGBA', (size, size), (0, 0, 0, 0))
draw = ImageDraw.Draw(img)
# 绘制圆形背景
margin = 20
draw.ellipse(
[margin, margin, size-margin, size-margin],
fill=(52, 152, 219, 255), # 蓝色背景
outline=(41, 128, 185, 255),
width=3
)
# 绘制字母T和M
try:
# 尝试使用系统字体
font = ImageFont.truetype("arial.ttf", 80)
except:
# 如果找不到字体,使用默认字体
font = ImageFont.load_default()
# 绘制文字
text = "TM"
# 获取文字边界框
bbox = draw.textbbox((0, 0), text, font=font)
text_width = bbox[2] - bbox[0]
text_height = bbox[3] - bbox[1]
# 计算文字位置(居中)
x = (size - text_width) // 2
y = (size - text_height) // 2 - 10
# 绘制白色文字
draw.text((x, y), text, fill=(255, 255, 255, 255), font=font)
# 保存为PNG
img.save('trulymem_icon.png', 'PNG')
print("图标已创建: trulymem_icon.png")
# 转换为ICO格式
try:
# 创建不同尺寸的图标
icon_sizes = [(16, 16), (32, 32), (48, 48), (64, 64), (128, 128), (256, 256)]
icons = []
for icon_size in icon_sizes:
icon = img.resize(icon_size, Image.Resampling.LANCZOS)
icons.append(icon)
# 保存为ICO
img.save('trulymem_icon.ico', format='ICO', sizes=icon_sizes)
print("ICO图标已创建: trulymem_icon.ico")
except Exception as e:
print(f"创建ICO失败: {e}")
print("请使用在线工具将PNG转换为ICO")
if __name__ == "__main__":
try:
create_icon()
except ImportError:
print("需要安装Pillow库: pip install Pillow")
sys.exit(1)

25
docs/README.md Normal file
View File

@ -0,0 +1,25 @@
# TrulyMEM 文档
欢迎来到TrulyMEM项目文档。
## 文档目录
- [架构设计](架构.md) - 系统架构和技术设计
- [快速开始](一键启动指南.md) - 一键启动指南
## 项目简介
TrulyMEM是一个让AI拥有长期记忆能力的图记忆系统通过图数据库存储实体关系让AI能够像人类一样记忆、回忆和管理信息。
## 核心特性
- 长期记忆存储
- 人设图机制
- 流式消息显示
- 跨平台支持
- 独立部署
## 快速链接
- [GitHub仓库](https://github.com/yourusername/trulymem)
- [问题反馈](https://github.com/yourusername/trulymem/issues)

View File

@ -523,6 +523,48 @@ class GraphMemoryClient:
def _build_system_prompt(self) -> str:
return """你是TrulyMEMTrueHumanMEM项目的AI助手拥有长期记忆能力。
## ⚠️ 最高优先级:人设图机制(每轮必读!)
**【强制要求】每轮对话开始前,必须执行以下步骤:**
1. **立即调用memory_recall**,查询参数:
```json
{
"query_intent": "AI,人设,角色,性格,语气,说话风格",
"depth": 2
}
```
2. **检查查询结果**
- 如果找到人设信息 → **严格按照人设回复,不得跳出角色**
- 如果没有找到 → 使用默认的TrulyMEM身份
3. **回复时必须遵守**
- 人设优先级 > 默认身份
- 每句话都符合人设的语气、风格、特征
- 绝不主动跳出角色,除非用户明确要求
### 人设图结构
- AI节点人设图中心节点
- 角色属性:性格、语气、说话风格、行为特征
- 用户要求:用户指定的角色要求
### 用户要求角色扮演时
立即使用memory_commit写入
```json
{
"triplets": [
{"subject": "AI", "relation": "扮演角色", "object": "猫娘"},
{"subject": "AI", "relation": "说话风格", "object": "可爱俏皮"},
{"subject": "AI", "relation": "语气特征", "object": "使用喵结尾"},
{"subject": "AI", "relation": "性格特点", "object": "活泼粘人"}
]
}
```
然后立即按照新人设回复!
---
## 身份说明
- 你的名字是TrulyMEM是TrueHumanMEM项目的产物
- 你拥有基于图数据库的长期记忆能力
@ -530,12 +572,14 @@ class GraphMemoryClient:
## 核心职责
你是一个智能对话助手,**图数据库是你记忆的唯一载体**。你的主要任务是:
1. 与用户进行自然、流畅的对话
2. 回答问题、提供建议、协助完成任务
3. 根据对话内容灵活查询和使用记忆
4. 将用户明确提到的信息写入记忆
1. **每轮对话前先查询人设图(最高优先级)**
2. 与用户进行自然、流畅的对话
3. 回答问题、提供建议、协助完成任务
4. 根据对话内容灵活查询和使用记忆
5. 将用户明确提到的信息写入记忆
**重要**
- **人设图优先:每轮对话前必须查询人设,严格按照人设回复**
- 图数据库是你记忆的唯一来源,没有其他记忆方式
- 优先进行自然对话,根据需要灵活调用记忆工具
- 用户明确提到的内容必须写入,推理得到的内容必须标注

View File

@ -0,0 +1,50 @@
"""核心逻辑导入测试"""
import pytest
def test_import_neo4j_graph():
"""测试 Neo4jGraph 类导入"""
from graph_memory_tui.core.imports import Neo4jGraph
assert Neo4jGraph is not None
assert hasattr(Neo4jGraph, 'recall')
assert hasattr(Neo4jGraph, 'commit')
assert hasattr(Neo4jGraph, 'purge')
def test_import_graph_memory_client():
"""测试 GraphMemoryClient 类导入"""
from graph_memory_tui.core.imports import GraphMemoryClient
assert GraphMemoryClient is not None
assert hasattr(GraphMemoryClient, 'send_message')
def test_import_tools():
"""测试 TOOLS 定义导入"""
from graph_memory_tui.core.imports import TOOLS
assert TOOLS is not None
assert isinstance(TOOLS, list)
assert len(TOOLS) > 0
assert any(t['function']['name'] == 'memory_recall' for t in TOOLS)
def test_import_execute_tool():
"""测试 execute_tool 函数导入"""
from graph_memory_tui.core.imports import execute_tool
assert execute_tool is not None
assert callable(execute_tool)
def test_import_config_vars():
"""测试配置变量导入"""
from graph_memory_tui.core.imports import (
DEEPSEEK_API_KEY,
DEEPSEEK_BASE_URL,
MODEL_NAME,
NEO4J_URI,
NEO4J_USER,
NEO4J_PASSWORD,
)
assert DEEPSEEK_BASE_URL is not None
assert MODEL_NAME is not None
assert NEO4J_URI is not None

View File

@ -0,0 +1,33 @@
"""焦点处理器测试"""
import pytest
from graph_memory_tui.handlers.focus_handler import FocusHandler
def test_focus_handler_creation():
"""测试焦点处理器创建"""
handler = FocusHandler()
assert handler is not None
assert handler._current_index == 0
def test_focus_ring():
"""测试焦点循环"""
handler = FocusHandler()
assert len(handler.FOCUS_RING) == 5
assert "input-textarea" in handler.FOCUS_RING
assert "cypher-textarea" in handler.FOCUS_RING
def test_get_current_focus_name():
"""测试获取当前焦点名称"""
handler = FocusHandler()
name = handler.get_current_focus_name()
assert name == "Input"
def test_focus_names_mapping():
"""测试焦点名称映射"""
handler = FocusHandler()
assert handler.FOCUS_NAMES["input-textarea"] == "Input"
assert handler.FOCUS_NAMES["cypher-textarea"] == "Query"

View File

@ -0,0 +1,83 @@
"""数据模型测试"""
import pytest
from datetime import datetime
from graph_memory_tui.models.message import Message, ToolCall, ToolResult
from graph_memory_tui.models.config import AppConfig
from graph_memory_tui.models.log_entry import LogEntry
def test_message_creation(sample_message):
"""测试消息创建"""
assert sample_message.role == "user"
assert sample_message.content == "测试消息"
assert isinstance(sample_message.timestamp, datetime)
def test_message_with_tool_calls():
"""测试带工具调用的消息"""
tool_call = ToolCall(
id="test-id",
name="memory_recall",
arguments={"query_intent": "测试"}
)
message = Message(
role="assistant",
content="测试回复",
tool_calls=[tool_call]
)
assert message.role == "assistant"
assert message.tool_calls is not None
assert len(message.tool_calls) == 1
assert message.tool_calls[0].name == "memory_recall"
def test_tool_call_creation(sample_tool_call):
"""测试工具调用创建"""
assert sample_tool_call.id == "test-call-id"
assert sample_tool_call.name == "memory_recall"
assert sample_tool_call.arguments == {"query_intent": "测试查询"}
def test_tool_result_creation(sample_tool_result):
"""测试工具结果创建"""
assert sample_tool_result.tool_call_id == "test-call-id"
assert sample_tool_result.success is True
assert sample_tool_result.result == "测试结果"
def test_config_creation(sample_config):
"""测试配置创建"""
assert sample_config.api_key == "test-api-key"
assert sample_config.model == "test-model"
assert sample_config.base_url == "https://test.api.com"
def test_config_from_env():
"""测试从环境变量加载配置"""
import os
os.environ["DEEPSEEK_API_KEY"] = "env-api-key"
os.environ["MODEL_NAME"] = "env-model"
config = AppConfig.from_env()
assert config.api_key == "env-api-key"
assert config.model == "env-model"
def test_log_entry_creation(sample_log_entry):
"""测试日志条目创建"""
assert sample_log_entry.tool_name == "memory_recall"
assert sample_log_entry.duration == 0.5
def test_log_entry_summary(sample_log_entry):
"""测试日志条目摘要"""
args_summary = sample_log_entry.args_summary
result_summary = sample_log_entry.result_summary
assert isinstance(args_summary, str)
assert isinstance(result_summary, str)
assert len(args_summary) <= 53 # 50 + "..."
assert len(result_summary) <= 103 # 100 + "..."

44
trulymem_entry.py Normal file
View File

@ -0,0 +1,44 @@
#!/usr/bin/env python3
"""
TrulyMEM 独立入口文件
用于打包为可执行文件
"""
import sys
import os
from pathlib import Path
# 确保工作目录正确
if getattr(sys, 'frozen', False):
# 打包后的可执行文件
application_path = Path(sys.executable).parent
else:
# 开发环境
application_path = Path(__file__).parent
# 切换到应用目录
os.chdir(application_path)
# 添加项目路径
if str(application_path) not in sys.path:
sys.path.insert(0, str(application_path))
# 导入并运行应用
from graph_memory_tui.app import GraphMemoryApp
def main():
"""主函数"""
try:
app = GraphMemoryApp()
app.run()
except KeyboardInterrupt:
print("\n应用已退出")
sys.exit(0)
except Exception as e:
print(f"应用启动失败: {e}")
import traceback
traceback.print_exc()
sys.exit(1)
if __name__ == "__main__":
main()

BIN
trulymem_icon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 141 KiB

BIN
trulymem_icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB