chunking.py 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. from __future__ import annotations
  2. import hashlib
  3. import json
  4. from app.core.knowledge.contracts import KnowledgeChunkDraft, KnowledgeSnapshot
  5. def _hash(payload: object) -> str:
  6. value = json.dumps(
  7. payload, ensure_ascii=False, sort_keys=True, separators=(",", ":")
  8. )
  9. return hashlib.sha256(value.encode("utf-8")).hexdigest()
  10. def _chunk_kind(semantic_path: str) -> str:
  11. root = semantic_path.split("/", 1)[0]
  12. return {
  13. "name": "summary",
  14. "aliases": "summary",
  15. "purpose": "definition",
  16. "definition": "definition",
  17. "owner": "field",
  18. "fields": "field",
  19. "rules": "field",
  20. }.get(root, "relation")
  21. def build_chunks(snapshot: KnowledgeSnapshot) -> tuple[KnowledgeChunkDraft, ...]:
  22. chunks = []
  23. for point in snapshot.points:
  24. point_set_hash = _hash(
  25. {
  26. "point_key": point.point_key,
  27. "content_hash": point.content_hash,
  28. "metadata_hash": point.metadata_hash,
  29. "permission_hash": point.permission_hash,
  30. }
  31. )
  32. chunks.append(
  33. KnowledgeChunkDraft(
  34. chunk_key=_hash(
  35. {
  36. "point_key": point.point_key,
  37. "point_set_hash": point_set_hash,
  38. }
  39. ),
  40. chunk_kind=_chunk_kind(point.semantic_path),
  41. section_path=point.semantic_path,
  42. content=point.content,
  43. content_hash=point.content_hash,
  44. lexical_text=point.content,
  45. primary_point_key=point.point_key,
  46. point_keys=(point.point_key,),
  47. point_set_hash=point_set_hash,
  48. metadata={
  49. **point.metadata,
  50. "source_type": snapshot.source_type,
  51. "source_uid": snapshot.source_uid,
  52. "source_revision": snapshot.source_revision,
  53. "permission_scope": point.permission_scope,
  54. },
  55. )
  56. )
  57. return tuple(chunks)
  58. def embedding_input_hash(chunk: KnowledgeChunkDraft, profile_key: str) -> str:
  59. return _hash(
  60. {
  61. "profile_key": profile_key,
  62. "content_hash": chunk.content_hash,
  63. "content": chunk.content,
  64. }
  65. )