routes.py 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. from fastapi import APIRouter, Depends, HTTPException, Query
  2. from sqlalchemy import text
  3. from sqlalchemy.orm import Session
  4. from core_domain import ServiceHealth
  5. from app.application.document_parsers import DocumentParseError
  6. from app.application.services import KnowledgeApplicationService
  7. from app.bootstrap.settings import KnowledgeServiceSettings
  8. from app.db.session import get_db
  9. from app.domain.repositories import (
  10. KnowledgeBaseRepository,
  11. KnowledgeChunkRepository,
  12. KnowledgeDocumentRepository,
  13. )
  14. from app.schemas.knowledge import (
  15. KnowledgeBaseCreateRequest,
  16. KnowledgeBaseResponse,
  17. KnowledgeBaseStatusUpdateRequest,
  18. KnowledgeChunkResponse,
  19. KnowledgeDocumentCreateRequest,
  20. KnowledgeDocumentIngestResponse,
  21. KnowledgeDocumentParseRequest,
  22. KnowledgeDocumentParseResponse,
  23. KnowledgeDocumentResponse,
  24. KnowledgeSearchRequest,
  25. KnowledgeSearchResultResponse,
  26. )
  27. router = APIRouter()
  28. def get_knowledge_settings() -> KnowledgeServiceSettings:
  29. return KnowledgeServiceSettings()
  30. def get_knowledge_application_service(
  31. db: Session = Depends(get_db),
  32. settings: KnowledgeServiceSettings = Depends(get_knowledge_settings),
  33. ) -> KnowledgeApplicationService:
  34. return KnowledgeApplicationService(
  35. settings=settings,
  36. base_repository=KnowledgeBaseRepository(db),
  37. document_repository=KnowledgeDocumentRepository(db),
  38. chunk_repository=KnowledgeChunkRepository(db),
  39. )
  40. @router.get("/health", response_model=ServiceHealth)
  41. def health_check(db: Session = Depends(get_db)) -> ServiceHealth:
  42. db.execute(text("SELECT 1"))
  43. return ServiceHealth(service="knowledge-service", status="ok", database="ok")
  44. @router.post("/bases", response_model=KnowledgeBaseResponse)
  45. def create_base(
  46. payload: KnowledgeBaseCreateRequest,
  47. service: KnowledgeApplicationService = Depends(get_knowledge_application_service),
  48. ) -> KnowledgeBaseResponse:
  49. return KnowledgeBaseResponse.from_entity(service.create_base(payload))
  50. @router.get("/bases", response_model=list[KnowledgeBaseResponse])
  51. def list_bases(
  52. tenant_id: str = Query(...),
  53. service: KnowledgeApplicationService = Depends(get_knowledge_application_service),
  54. ) -> list[KnowledgeBaseResponse]:
  55. return [
  56. KnowledgeBaseResponse.from_entity(item)
  57. for item in service.list_bases(tenant_id=tenant_id)
  58. ]
  59. @router.patch("/bases/{knowledge_base_id}/status", response_model=KnowledgeBaseResponse)
  60. def update_base_status(
  61. knowledge_base_id: str,
  62. payload: KnowledgeBaseStatusUpdateRequest,
  63. service: KnowledgeApplicationService = Depends(get_knowledge_application_service),
  64. ) -> KnowledgeBaseResponse:
  65. entity = service.update_base_status(
  66. knowledge_base_id=knowledge_base_id,
  67. payload=payload,
  68. )
  69. if entity is None:
  70. raise HTTPException(
  71. status_code=404,
  72. detail=f"knowledge base not found: {knowledge_base_id}",
  73. )
  74. return KnowledgeBaseResponse.from_entity(entity)
  75. @router.post("/documents", response_model=KnowledgeDocumentIngestResponse)
  76. def create_document(
  77. payload: KnowledgeDocumentCreateRequest,
  78. service: KnowledgeApplicationService = Depends(get_knowledge_application_service),
  79. ) -> KnowledgeDocumentIngestResponse:
  80. try:
  81. document, chunks = service.create_document(payload)
  82. except ValueError as exc:
  83. raise HTTPException(status_code=422, detail=str(exc)) from exc
  84. return KnowledgeDocumentIngestResponse(
  85. document=KnowledgeDocumentResponse.from_entity(document),
  86. chunks=[KnowledgeChunkResponse.from_entity(item) for item in chunks],
  87. )
  88. @router.post("/documents/parse", response_model=KnowledgeDocumentParseResponse)
  89. def parse_document(
  90. payload: KnowledgeDocumentParseRequest,
  91. service: KnowledgeApplicationService = Depends(get_knowledge_application_service),
  92. ) -> KnowledgeDocumentParseResponse:
  93. try:
  94. parsed = service.parse_document(payload)
  95. except DocumentParseError as exc:
  96. raise HTTPException(status_code=422, detail=str(exc)) from exc
  97. return KnowledgeDocumentParseResponse(
  98. content_text=parsed.content_text,
  99. source_type=parsed.source_type,
  100. metadata_json=parsed.metadata_json,
  101. )
  102. @router.get("/documents", response_model=list[KnowledgeDocumentResponse])
  103. def list_documents(
  104. tenant_id: str = Query(...),
  105. knowledge_base_id: str = Query(...),
  106. service: KnowledgeApplicationService = Depends(get_knowledge_application_service),
  107. ) -> list[KnowledgeDocumentResponse]:
  108. return [
  109. KnowledgeDocumentResponse.from_entity(item)
  110. for item in service.list_documents(
  111. tenant_id=tenant_id,
  112. knowledge_base_id=knowledge_base_id,
  113. )
  114. ]
  115. @router.post("/search", response_model=list[KnowledgeSearchResultResponse])
  116. def search(
  117. payload: KnowledgeSearchRequest,
  118. service: KnowledgeApplicationService = Depends(get_knowledge_application_service),
  119. ) -> list[KnowledgeSearchResultResponse]:
  120. return [
  121. KnowledgeSearchResultResponse(
  122. chunk=KnowledgeChunkResponse.from_entity(chunk),
  123. document=KnowledgeDocumentResponse.from_entity(document),
  124. score=score,
  125. score_json=score_json,
  126. )
  127. for chunk, document, score, score_json in service.search(payload)
  128. ]