knowledge_query.py 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. from __future__ import annotations
  4. import sqlite3
  5. from pathlib import Path
  6. from typing import Any, Dict, List
  7. class KnowledgeQuery:
  8. def __init__(self, project_root: Path):
  9. self.project_root = Path(project_root)
  10. self._db_path = self.project_root / ".webnovel" / "index.db"
  11. def entity_state_at_chapter(self, entity_id: str, chapter: int) -> Dict[str, Any]:
  12. """查询实体在指定章节时的状态(从 state_changes 反推)。"""
  13. conn = sqlite3.connect(str(self._db_path))
  14. conn.row_factory = sqlite3.Row
  15. try:
  16. rows = conn.execute(
  17. """
  18. SELECT field, new_value
  19. FROM state_changes
  20. WHERE entity_id = ? AND chapter <= ?
  21. ORDER BY chapter ASC, id ASC
  22. """,
  23. (entity_id, chapter),
  24. ).fetchall()
  25. state: Dict[str, str] = {}
  26. for row in rows:
  27. field = str(row["field"] or "").strip()
  28. if field:
  29. state[field] = str(row["new_value"] or "").strip()
  30. return {
  31. "entity_id": entity_id,
  32. "at_chapter": chapter,
  33. "state_at_chapter": state,
  34. }
  35. finally:
  36. conn.close()
  37. def entity_relationships_at_chapter(self, entity_id: str, chapter: int) -> Dict[str, Any]:
  38. """查询实体在指定章节时的所有关系。"""
  39. conn = sqlite3.connect(str(self._db_path))
  40. conn.row_factory = sqlite3.Row
  41. try:
  42. rows = conn.execute(
  43. """
  44. SELECT from_entity, to_entity, relationship_type, description, chapter
  45. FROM relationship_events
  46. WHERE (from_entity = ? OR to_entity = ?) AND chapter <= ?
  47. ORDER BY chapter ASC, id ASC
  48. """,
  49. (entity_id, entity_id, chapter),
  50. ).fetchall()
  51. latest: Dict[str, Dict[str, Any]] = {}
  52. for row in rows:
  53. from_e = str(row["from_entity"] or "").strip()
  54. to_e = str(row["to_entity"] or "").strip()
  55. pair_key = tuple(sorted([from_e, to_e]))
  56. latest[str(pair_key)] = {
  57. "from_entity": from_e,
  58. "to_entity": to_e,
  59. "relationship_type": str(row["relationship_type"] or "").strip(),
  60. "description": str(row["description"] or "").strip(),
  61. "since_chapter": int(row["chapter"] or 0),
  62. }
  63. return {
  64. "entity_id": entity_id,
  65. "at_chapter": chapter,
  66. "relationships": list(latest.values()),
  67. }
  68. finally:
  69. conn.close()