| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107 |
- """阅读历史记录 —— 对话会话持久化、恢复与上下文延续."""
- from __future__ import annotations
- import sqlite3
- import time
- from contextlib import contextmanager
- from ...utils.common import exec_sql
- def ensure_tables(db_path: str) -> None:
- exec_sql(db_path,
- "CREATE TABLE IF NOT EXISTS paper_reader_turns(id INTEGER PRIMARY KEY AUTOINCREMENT,paper_id INTEGER NOT NULL,role TEXT NOT NULL,content TEXT NOT NULL,created_at INTEGER NOT NULL)",
- "CREATE INDEX IF NOT EXISTS idx_paper_reader_turns_paper ON paper_reader_turns(paper_id,created_at)",
- )
- @contextmanager
- def _conn(db_path: str, *, row_factory=None):
- conn = sqlite3.connect(db_path)
- if row_factory:
- conn.row_factory = row_factory
- try:
- yield conn
- conn.commit()
- finally:
- conn.close()
- def append_turn(db_path: str, *, paper_id: int, role: str, content: str) -> None:
- ensure_tables(db_path)
- role2 = (role or "").strip().lower()
- if role2 not in ("user", "assistant"):
- role2 = "user"
- text = (content or "").strip()
- if not text:
- return
- now = int(time.time())
- with _conn(db_path) as conn:
- conn.execute(
- "INSERT INTO paper_reader_turns(paper_id,role,content,created_at) VALUES(?,?,?,?)",
- (int(paper_id), role2, text, now),
- )
- def prepend_turn(
- db_path: str,
- *,
- paper_id: int,
- role: str,
- content: str,
- before_created_at: int,
- ) -> None:
- ensure_tables(db_path)
- role2 = (role or "").strip().lower()
- if role2 not in ("user", "assistant"):
- role2 = "user"
- text = (content or "").strip()
- if not text:
- return
- ts = int(before_created_at) - 1
- if ts < 0:
- ts = 0
- now = int(time.time())
- if ts >= now:
- ts = now - 1
- with _conn(db_path) as conn:
- conn.execute(
- "INSERT INTO paper_reader_turns(paper_id,role,content,created_at) VALUES(?,?,?,?)",
- (int(paper_id), role2, text, ts),
- )
- def ensure_opening_turn(db_path: str, *, paper_id: int, opening_text: str) -> None:
- op = (opening_text or "").strip()
- if not op:
- return
- turns = list_turns(db_path, paper_id=int(paper_id), limit=5)
- if not turns:
- append_turn(db_path, paper_id=int(paper_id), role="assistant", content=op)
- return
- first = turns[0]
- r0 = (first.get("role") or "").strip().lower()
- c0 = (first.get("content") or "").strip()
- if r0 == "assistant" and c0 == op:
- return
- if r0 == "assistant":
- return
- if r0 == "user":
- try:
- ts0 = int(first.get("created_at") or 0)
- except Exception:
- ts0 = int(time.time())
- prepend_turn(db_path, paper_id=int(paper_id), role="assistant", content=op, before_created_at=ts0)
- return
- def list_turns(db_path: str, *, paper_id: int, limit: int = 200) -> list[dict[str, str | None]]:
- ensure_tables(db_path)
- with _conn(db_path, row_factory=sqlite3.Row) as conn:
- rows = conn.execute(
- "SELECT role,content,created_at FROM paper_reader_turns WHERE paper_id=? ORDER BY created_at ASC,id ASC LIMIT ?",
- (int(paper_id), int(limit)),
- ).fetchall()
- out: list[dict[str, str | None]] = []
- for r in rows:
- out.append({
- "role": (r["role"] or "").strip(),
- "content": (r["content"] or "").strip(),
- "created_at": int(r["created_at"] or 0),
- })
- return out
|