feat: 搜索改进与代码修复

- 连字符扩展:multi-agent → multi agent 提升搜索召回率
- 中文同义词支持:添加中英文混合查询扩展
- Snippet 高亮预留:为 FTS5 snippet 功能预留接口
- YAML 解析增强:支持 HTML 实体解码
- 标签关联维护:自动维护 wiki_page_tags 关联表
- 缓存失效优化:支持智能前缀匹配
- 设计文档更新:汇总近期改动 (v1.3)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-28 07:47:28 +08:00
parent b2c3ca02f0
commit 421b3ada3b
10 changed files with 289 additions and 44 deletions
+46
View File
@@ -9,6 +9,7 @@ Service Layer - ParserService(解析服务)
import re
import logging
import json
import html
from typing import List, Dict, Optional, Tuple
from datetime import datetime
from pathlib import Path
@@ -36,6 +37,48 @@ class ParserService:
# Tag 正则(frontmatter 中的 tags 字段)
TAG_PATTERN = re.compile(r'tags:\s*\[(.*?)\]')
def _fix_yaml_common_issues(self, yaml_content: str) -> str:
"""修复常见的 YAML 格式问题
1. HTML 实体解码
2. 修复一级键值对中的冒号问题(不处理嵌套)
"""
# 解码 HTML 实体
yaml_content = html.unescape(yaml_content)
# 修复一级键值对中的冒号问题
# 只处理格式为 "key: value" 的行(不处理嵌套的缩进行)
lines = []
for line in yaml_content.split('\n'):
stripped = line.strip()
# 跳过空行、注释、列表项、多行标记
if not stripped or stripped.startswith('#') or stripped.startswith('-') or stripped.startswith('>'):
lines.append(line)
continue
# 只处理一级键值对(没有缩进或缩进较少)
# 检查是否是简单的 "key: value" 格式
if ':' in line and not line.startswith(' ') and not line.startswith('\t'):
parts = line.split(':', 1)
if len(parts) == 2:
key = parts[0].strip()
value = parts[1].strip()
# 如果值包含冒号且没有引号,添加引号
if value and ':' in value and not (value.startswith('"') or value.startswith("'") or value.startswith('|')):
# 检查值不是特殊格式
if not value.startswith('>') and not value.startswith('|'):
value = f'"{value}"'
lines.append(f"{key}: {value}")
else:
lines.append(line)
else:
lines.append(line)
return '\n'.join(lines)
def parse_frontmatter(self, content: str) -> Dict:
"""
解析 frontmatter(使用 PyYAML
@@ -54,6 +97,9 @@ class ParserService:
if match:
yaml_content = match.group(1)
# 修复常见 YAML 问题
yaml_content = self._fix_yaml_common_issues(yaml_content)
# 使用 PyYAML 进行完整解析
if YAML_AVAILABLE:
try: