init: RAG 知识库服务初始提交
- 后端 API(Flask + Gunicorn) - RAG 引擎(混合检索 + 云端 Reranker + 引用溯源) - 文档解析(MinerU + 多格式支持) - Docker 生产部署配置 - 排除前端项目、敏感配置、模型文件
This commit is contained in:
5
repositories/__init__.py
Normal file
5
repositories/__init__.py
Normal file
@@ -0,0 +1,5 @@
|
||||
"""
|
||||
Repository 模块
|
||||
|
||||
提供数据访问层抽象,支持开发环境和生产环境的不同实现。
|
||||
"""
|
||||
65
repositories/session_repo.py
Normal file
65
repositories/session_repo.py
Normal file
@@ -0,0 +1,65 @@
|
||||
"""
|
||||
会话存储接口
|
||||
|
||||
定义会话管理的抽象接口,支持不同的存储实现。
|
||||
"""
|
||||
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import List, Dict, Optional
|
||||
|
||||
|
||||
class BaseSessionRepo(ABC):
|
||||
"""会话存储接口"""
|
||||
|
||||
@abstractmethod
|
||||
def get_history(self, session_id: str) -> List[Dict]:
|
||||
"""
|
||||
获取会话历史
|
||||
|
||||
Args:
|
||||
session_id: 会话ID
|
||||
|
||||
Returns:
|
||||
消息列表,每条消息包含 role、content 和可选的 metadata
|
||||
"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def add_message(self, session_id: str, role: str, content: str, metadata: Optional[Dict] = None) -> None:
|
||||
"""
|
||||
添加消息到会话
|
||||
|
||||
Args:
|
||||
session_id: 会话ID
|
||||
role: 角色(user/assistant)
|
||||
content: 消息内容
|
||||
metadata: 可选的元数据(如图片、来源等)
|
||||
"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def create_session(self, user_id: str, title: str = "新对话") -> str:
|
||||
"""
|
||||
创建新会话
|
||||
|
||||
Args:
|
||||
user_id: 用户ID
|
||||
title: 会话标题
|
||||
|
||||
Returns:
|
||||
会话ID
|
||||
"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_user_sessions(self, user_id: str) -> List[Dict]:
|
||||
"""
|
||||
获取用户的会话列表
|
||||
|
||||
Args:
|
||||
user_id: 用户ID
|
||||
|
||||
Returns:
|
||||
会话列表
|
||||
"""
|
||||
pass
|
||||
82
repositories/sqlite_session_repo.py
Normal file
82
repositories/sqlite_session_repo.py
Normal file
@@ -0,0 +1,82 @@
|
||||
"""
|
||||
SQLite 会话存储实现(开发环境)
|
||||
|
||||
使用本地 SQLite 数据库存储会话数据。
|
||||
"""
|
||||
|
||||
from .session_repo import BaseSessionRepo
|
||||
from typing import List, Dict, Optional
|
||||
import uuid
|
||||
from datetime import datetime
|
||||
import json
|
||||
|
||||
|
||||
class SQLiteSessionRepo(BaseSessionRepo):
|
||||
"""开发环境:SQLite存储"""
|
||||
|
||||
def __init__(self):
|
||||
from data.db import get_connection
|
||||
self.get_connection = get_connection
|
||||
|
||||
def get_history(self, session_id: str) -> List[Dict]:
|
||||
"""获取会话历史(包含 metadata)"""
|
||||
with self.get_connection("session") as conn:
|
||||
cursor = conn.execute(
|
||||
"SELECT role, content, metadata FROM messages WHERE session_id = ? ORDER BY created_at",
|
||||
(session_id,)
|
||||
)
|
||||
history = []
|
||||
for row in cursor.fetchall():
|
||||
msg = {"role": row[0], "content": row[1]}
|
||||
# 解析 metadata
|
||||
if row[2]:
|
||||
try:
|
||||
msg["metadata"] = json.loads(row[2])
|
||||
except (json.JSONDecodeError, TypeError):
|
||||
msg["metadata"] = {}
|
||||
history.append(msg)
|
||||
return history
|
||||
|
||||
def add_message(self, session_id: str, role: str, content: str, metadata: Optional[Dict] = None) -> None:
|
||||
"""添加消息到会话(支持 metadata)"""
|
||||
metadata_str = json.dumps(metadata, ensure_ascii=False) if metadata else None
|
||||
with self.get_connection("session") as conn:
|
||||
conn.execute(
|
||||
"INSERT INTO messages (session_id, role, content, metadata, created_at) VALUES (?, ?, ?, ?, ?)",
|
||||
(session_id, role, content, metadata_str, datetime.now().isoformat())
|
||||
)
|
||||
|
||||
def update_last_active(self, session_id: str) -> None:
|
||||
"""更新会话最后活跃时间"""
|
||||
with self.get_connection("session") as conn:
|
||||
conn.execute(
|
||||
"UPDATE sessions SET last_active = ? WHERE session_id = ?",
|
||||
(datetime.now().isoformat(), session_id)
|
||||
)
|
||||
|
||||
def create_session(self, user_id: str, title: str = "新对话") -> str:
|
||||
"""创建新会话"""
|
||||
session_id = str(uuid.uuid4())
|
||||
with self.get_connection("session") as conn:
|
||||
conn.execute(
|
||||
"INSERT INTO sessions (session_id, user_id, created_at, last_active) VALUES (?, ?, ?, ?)",
|
||||
(session_id, user_id, datetime.now().isoformat(), datetime.now().isoformat())
|
||||
)
|
||||
return session_id
|
||||
|
||||
def get_user_sessions(self, user_id: str) -> List[Dict]:
|
||||
"""获取用户的会话列表"""
|
||||
with self.get_connection("session") as conn:
|
||||
cursor = conn.execute(
|
||||
"SELECT session_id, created_at, last_active FROM sessions WHERE user_id = ? ORDER BY last_active DESC",
|
||||
(user_id,)
|
||||
)
|
||||
return [
|
||||
{
|
||||
"session_id": row[0],
|
||||
"title": "对话", # 默认标题
|
||||
"created_at": row[1],
|
||||
"last_active": row[2]
|
||||
}
|
||||
for row in cursor.fetchall()
|
||||
]
|
||||
28
repositories/stateless_session_repo.py
Normal file
28
repositories/stateless_session_repo.py
Normal file
@@ -0,0 +1,28 @@
|
||||
"""
|
||||
无状态会话存储实现(生产环境)
|
||||
|
||||
生产环境不存储会话数据,历史由后端传入。
|
||||
"""
|
||||
|
||||
from .session_repo import BaseSessionRepo
|
||||
from typing import List, Dict, Optional
|
||||
|
||||
|
||||
class StatelessSessionRepo(BaseSessionRepo):
|
||||
"""生产环境:无状态,不存储"""
|
||||
|
||||
def get_history(self, session_id: str) -> List[Dict]:
|
||||
"""生产环境:历史由后端传入,不查询"""
|
||||
return []
|
||||
|
||||
def add_message(self, session_id: str, role: str, content: str, metadata: Optional[Dict] = None) -> None:
|
||||
"""生产环境:不存储消息"""
|
||||
pass
|
||||
|
||||
def create_session(self, user_id: str, title: str = "新对话") -> str:
|
||||
"""生产环境:不创建会话,返回占位符"""
|
||||
return "stateless"
|
||||
|
||||
def get_user_sessions(self, user_id: str) -> List[Dict]:
|
||||
"""生产环境:会话列表由后端管理"""
|
||||
return []
|
||||
Reference in New Issue
Block a user