vector_utils.py 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. import hashlib
  2. import math
  3. import requests
  4. import logging
  5. from typing import List
  6. from app.core.config import config_handler
  7. logger = logging.getLogger(__name__)
  8. # Read config
  9. EMBEDDING_BASE_URL = config_handler.get("admin_app", "EMBEDDING_BASE_URL", "")
  10. EMBEDDING_MODEL = config_handler.get("admin_app", "EMBEDDING_MODEL", "")
  11. EMBEDDING_API_KEY = config_handler.get("admin_app", "EMBEDDING_API_KEY", "dummy")
  12. def text_to_vector_algo(text: str, dim: int = 768) -> List[float]:
  13. """
  14. 调用 Embedding API 生成向量。
  15. 如果 API 调用失败,返回全 0 向量 (长度为 dim)。
  16. 注意:返回的向量维度取决于模型,可能与传入的 dim 不一致。
  17. """
  18. if not text:
  19. return [0.0] * dim
  20. # 如果没有配置 URL,回退到原来的哈希算法 (或者直接报错,视需求而定)
  21. # 这里为了防止完全无法运行,保留一个简单的 fallback,但打个 warning
  22. if not EMBEDDING_BASE_URL:
  23. logger.warning("未配置 EMBEDDING_BASE_URL,使用 Dummy Hash 向量")
  24. return _dummy_hash_vector(text, dim)
  25. try:
  26. url = f"{EMBEDDING_BASE_URL}/embeddings"
  27. headers = {
  28. "Content-Type": "application/json",
  29. "Authorization": f"Bearer {EMBEDDING_API_KEY}"
  30. }
  31. payload = {
  32. "input": text,
  33. "model": EMBEDDING_MODEL
  34. }
  35. # 简单重试机制
  36. response = requests.post(url, json=payload, headers=headers, timeout=30)
  37. response.raise_for_status()
  38. data = response.json()
  39. # 兼容 OpenAI 格式
  40. if 'data' in data and len(data['data']) > 0:
  41. embedding = data['data'][0]['embedding']
  42. return embedding
  43. else:
  44. logger.error(f"Embedding API 响应格式错误: {data}")
  45. return [0.0] * dim
  46. except Exception as e:
  47. logger.error(f"Embedding API 调用失败: {e}")
  48. return [0.0] * dim
  49. def _dummy_hash_vector(text: str, dim: int) -> List[float]:
  50. """原有的特征哈希算法,作为 fallback"""
  51. vector = [0.0] * dim
  52. tokens = list(text)
  53. for token in tokens:
  54. hash_obj = hashlib.md5(token.encode('utf-8'))
  55. hash_val = int(hash_obj.hexdigest(), 16)
  56. idx = hash_val % dim
  57. vector[idx] += 1.0
  58. magnitude = math.sqrt(sum(x*x for x in vector))
  59. if magnitude > 0:
  60. vector = [x / magnitude for x in vector]
  61. return vector