sample_center_client.py 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. # coding=utf-8
  2. """
  3. 样本中心 API 客户端
  4. 用于对接外部样本中心系统的知识库查询和批量入库接口
  5. """
  6. import time
  7. from typing import Dict, Optional
  8. import requests
  9. from django.conf import settings
  10. from django.utils.translation import gettext as _
  11. from common.exception.app_exception import AppApiException
  12. from common.utils.logger import maxkb_logger
  13. class SampleCenterClient:
  14. """样本中心 API 客户端"""
  15. def __init__(self, base_url: str = None, app_id: str = None, app_secret: str = None):
  16. self.base_url = (base_url or getattr(settings, 'SAMPLE_CENTER_BASE_URL', '')).rstrip('/')
  17. self.app_id = app_id or getattr(settings, 'SAMPLE_CENTER_APP_ID', '')
  18. self.app_secret = app_secret or getattr(settings, 'SAMPLE_CENTER_APP_SECRET', '')
  19. self._token = None
  20. self._token_expires_at = 0
  21. def _get_token(self) -> str:
  22. """获取访问令牌(自动缓存和刷新)"""
  23. if self._token and time.time() < self._token_expires_at - 60:
  24. return self._token
  25. url = f"{self.base_url}/api/v1/auth/token"
  26. payload = {
  27. "app_id": self.app_id,
  28. "app_secret": self.app_secret,
  29. }
  30. try:
  31. response = requests.post(url, json=payload, timeout=10)
  32. response.raise_for_status()
  33. result = response.json()
  34. if result.get('code') != '000000':
  35. raise AppApiException(500, _('Sample center auth failed: {msg}').format(
  36. msg=result.get('message', 'unknown error')))
  37. data = result['data']
  38. self._token = data['access_token']
  39. self._token_expires_at = time.time() + data.get('expires_in', 7200)
  40. return self._token
  41. except requests.exceptions.RequestException as e:
  42. maxkb_logger.error(f'Sample center auth request failed: {e}')
  43. raise AppApiException(502, _('Failed to connect to sample center: {error}').format(error=str(e)))
  44. def _request(self, method: str, path: str, **kwargs) -> Dict:
  45. """统一请求方法"""
  46. token = self._get_token()
  47. url = f"{self.base_url}{path}"
  48. headers = {
  49. 'Authorization': f'Bearer {token}',
  50. 'X-App-Id': self.app_id,
  51. 'Content-Type': 'application/json',
  52. }
  53. headers.update(kwargs.pop('headers', {}))
  54. try:
  55. response = requests.request(method, url, headers=headers, timeout=30, **kwargs)
  56. response.raise_for_status()
  57. result = response.json()
  58. if result.get('code') != '000000':
  59. raise AppApiException(500, _('Sample center API error: {msg}').format(
  60. msg=result.get('message', 'unknown error')))
  61. return result.get('data', {})
  62. except requests.exceptions.RequestException as e:
  63. maxkb_logger.error(f'Sample center API request failed: {e}')
  64. raise AppApiException(502, _('Failed to connect to sample center: {error}').format(error=str(e)))
  65. def list_knowledge_bases(self, page: int = 1, page_size: int = 20) -> Dict:
  66. """查询知识库列表"""
  67. params = {'page': page, 'page_size': page_size}
  68. return self._request('GET', '/api/v1/knowledge-bases', params=params)
  69. def get_knowledge_base(self, kb_id: str) -> Dict:
  70. """查询知识库详情"""
  71. return self._request('GET', f'/api/v1/knowledge-bases/{kb_id}')
  72. def batch_import(self, kb_id: str, task_no: str, parents: list,
  73. children: list = None, callback_url: str = None) -> Dict:
  74. """提交批量入库任务"""
  75. payload = {
  76. 'task_no': task_no,
  77. 'parents': parents,
  78. }
  79. if children:
  80. payload['children'] = children
  81. if callback_url:
  82. payload['callback_url'] = callback_url
  83. return self._request('POST', f'/api/v1/knowledge-bases/{kb_id}/batch-import', json=payload)
  84. def get_import_task(self, task_id: str) -> Dict:
  85. """查询批量入库任务状态"""
  86. return self._request('GET', f'/api/v1/knowledge-bases/batch-import/{task_id}')
  87. def get_sample_center_client(**kwargs) -> SampleCenterClient:
  88. """获取样本中心客户端实例"""
  89. return SampleCenterClient(**kwargs)