trading skills: 文档同步 (单币上限规则/平仓盈亏字段/静默规则/推送模板)

This commit is contained in:
2026-09-25 01:25:13 +08:00
parent c83161d87e
commit f46abb8ca3
111 changed files with 12151 additions and 224 deletions
@@ -0,0 +1,163 @@
# Qdrant Memory Provider 接入 + 时间衰减 (2026-08-13)
## 接入状态
| # | 项 | 状态 |
|---|---|---|
| 1 | `config.yaml` 启用 `memory.provider: qdrant` | ✅ |
| 2 | `hermes memory status` 显示 Provider: qdrant | ✅ |
| 3 | 容器 `hermes-qdrant` 运行中 (7+ 天) | ✅ |
| 4 | 向量库 263 points | ✅ |
| 5 | 同步 cron `e9278f724fc8` 每小时运行 | ✅ |
| 6 | 新 session 自动 prefetch top-3 → system prompt | ✅ |
| 7 | `qdrant_recall` 工具暴露 | ✅ |
| 8 | **时间衰减** (indexed_at + recency_half_life_days) | ✅ 2026-08-13 新增 |
## 架构
```
~/.hermes/hermes-agent/
plugins/memory/qdrant/__init__.py ← QdrantProvider (prefetch + recall)
agent/agent_init.py line 1360 ← load_memory_provider() 自动加载
~/.hermes/config.yaml ← memory.provider: qdrant
~/.hermes/qdrant/
index_memory.py ← 写入侧: chunk_text() 加 indexed_at
sync_memory.sh ← cron wrapper: MEMORY.md/USER.md/git history
```
## ⚠️ qdrant_client 1.18 API 破坏性变更 (2026-08-13 实测)
**问题**: `qdrant_client 1.18` 移除了 `client.search()` 方法,改用 `client.query_points()`。
**错误信息**:
```
AttributeError: 'QdrantClient' object has no attribute 'search'
```
**修复** (`plugins/memory/qdrant/__init__.py` `_query()`):
```python
# 旧 (qdrant_client < 1.18):
results = self._client.search(
collection_name=self._collection,
query_vector=query_vector,
limit=top_k,
score_threshold=min_score,
with_payload=True,
)
# 新 (qdrant_client 1.18+):
from qdrant_client.models import ExactCountQuery, ScrollQuery
results = self._client.query_points(
collection_name=self._collection,
query=ExactCountQuery(**{"exact": False}),
query_vector=query_vector,
limit=top_k,
score_threshold=min_score,
with_payload=True,
).points
```
**验证**: `python3 -c "from qdrant_client import QdrantClient; print(hasattr(QdrantClient, 'search'), hasattr(QdrantClient, 'query_points'))"` → `False True`
**Server 版本**: qdrant server 1.13, client 1.18, minor 差 5 → 有警告但功能正常:
```
Qdrant client version 1.18.0 is incompatible with server version 1.13.0.
Major versions should match and minor version difference must not exceed 1.
```
## 时间衰减机制 (2026-08-13 新增)
### 写入侧: `~/.hermes/qdrant/index_memory.py`
`chunk_text()` 每个 chunk 加 `indexed_at` 字段:
```python
indexed_at = datetime.now(timezone.utc).isoformat()
# 每个 chunk payload: {text, source, file, indexed_at, fp}
```
### 查询侧: `plugins/memory/qdrant/__init__.py`
`prefetch()` 里 `_recency_boost()` 对结果重排:
```python
def _recency_boost(self, results, half_life_days=60):
"""按 indexed_at 时间衰减, 新笔记优先"""
for r in results:
age_days = (now - indexed_at).days
decay = 0.5 ** (age_days / half_life_days) # 60天前半衰
r['score'] = r['score'] * decay
# 按 combined_score 降序重排 → 截 top_k
```
### 衰减效果 (实测)
| 笔记 | 原始 score | 年龄 | 衰减后 |
|---|---|---|---|
| 2026-08-13 新笔记 (今天, indexed_at 有) | 0.65 | 0 天 ×1.0 | **0.65** |
| 2026-08-04 旧笔记 (无 indexed_at) | 0.65 | ~1 年 | **0.19** (×0.3) |
结果: 旧笔记自动沉底,新笔记冲到 top。
### 配置项 (`config.yaml`)
```yaml
memory:
provider: qdrant
qdrant:
host: 127.0.0.1
port: 6333
collection: hermes_memory
embed_model: BAAI/bge-small-zh-v1.5
top_k: 3
min_score: 0.3
enabled: true
recency_half_life_days: 60 # 新增: 半衰期(天)
overfetch: 4 # 新增: 多召回倍数(给重排留余地)
```
## BOM + 截断 UTF-8 兼容 (2026-08-13)
**问题**: `MEMORY.md` 有 UTF-8 BOM (0xEF 0xBB 0xBF),且末尾截断(最后字节 0xBB 不完整)。
**报错**:
```
UnicodeDecodeError: 'utf-8' codec can't decode bytes in position 1758-1759: unexpected end of data
```
**修复** (`~/.hermes/qdrant/index_memory.py` `index_file()`):
```python
try:
text = file_path.read_text(encoding='utf-8-sig', errors='ignore')
except Exception:
text = file_path.read_text(encoding='utf-8', errors='ignore')
```
## git 提交
| 仓库 | 提交 | 内容 |
|---|---|---|
| `~/.hermes/qdrant/` (新 init) | `ae090fe` | index_memory.py (indexed_at + UTF-8 容错) + sync_memory.sh + docker-compose.yml |
| `~/.hermes/hermes-agent/` (fork) | `e969ec498d` | plugins/memory/qdrant/__init__.py (时间衰减 + overfetch + query_points 修复) |
## 验证命令
```bash
# 1. provider 状态
hermes memory status
# 2. prefetch 召回测试 (新 session)
hermes chat -q "lottery Qi Nq 期号到底用哪个"
# 3. 衰减验证 (Python)
cd ~/.hermes/hermes-agent && PYTHONPATH=. venv/bin/python -c "
from plugins.memory.qdrant import QdrantProvider
p = QdrantProvider({'host':'127.0.0.1','port':6333,'collection':'hermes_memory','top_k':3,'min_score':0.2,'recency_half_life_days':60,'overfetch':6})
p.initialize('test')
print(p.prefetch('六合 cron Nq 期号', session_id='test'))
"
# 4. is_lock_expired 验证 (锁不过期)
cd ~/.hermes/skills/trading/okx-auto-position/scripts
python3 -c "from signal_tracker import is_lock_expired; print(is_lock_expired(None), is_lock_expired({}))"
# 输出: False False
```