0
0

_chapter2_config.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. import hashlib
  2. import math
  3. import os
  4. import re
  5. from pathlib import Path
  6. from typing import Iterable, List
  7. CODE_DIR = Path(__file__).resolve().parent
  8. def load_chapter2_env() -> None:
  9. try:
  10. from dotenv import load_dotenv
  11. except ModuleNotFoundError:
  12. return
  13. load_dotenv(CODE_DIR / ".env")
  14. load_dotenv()
  15. load_chapter2_env()
  16. def env_value(*names: str, default: str = "") -> str:
  17. for name in names:
  18. value = os.getenv(name)
  19. if value:
  20. return value
  21. return default
  22. def openai_config() -> dict:
  23. return {
  24. "base_url": env_value("base_url", "BASE_URL", default="https://api.modelverse.cn/v1"),
  25. "api_key": env_value("api_key", "API_KEY", default=""),
  26. "model": env_value("model", "MODEL", default="gpt-5.5"),
  27. }
  28. def get_chat_model(temperature: float = 0):
  29. provider = env_value("MODEL_PROVIDER", default="openai").lower()
  30. if provider == "ollama":
  31. from langchain_ollama import ChatOllama
  32. return ChatOllama(
  33. model=env_value("OLLAMA_MODEL", default="qwen2.5:7b"),
  34. base_url=env_value("OLLAMA_BASE_URL", default="http://127.0.0.1:11434"),
  35. temperature=temperature,
  36. )
  37. from langchain_openai import ChatOpenAI
  38. conf = openai_config()
  39. if not conf["api_key"]:
  40. raise RuntimeError("没有找到 api_key/API_KEY,请检查 代码/.env。")
  41. return ChatOpenAI(
  42. base_url=conf["base_url"],
  43. api_key=conf["api_key"],
  44. model=conf["model"],
  45. temperature=temperature,
  46. )
  47. def get_ollama_llm(temperature: float = 0):
  48. from langchain_ollama import OllamaLLM
  49. return OllamaLLM(
  50. model=env_value("OLLAMA_MODEL", default="qwen2.5:7b"),
  51. base_url=env_value("OLLAMA_BASE_URL", default="http://127.0.0.1:11434"),
  52. temperature=temperature,
  53. )
  54. def as_text(result) -> str:
  55. return getattr(result, "content", result)
  56. class HashEmbeddings:
  57. """Small local embedding model for classroom demos without external services."""
  58. def __init__(self, dim: int = 64):
  59. self.dim = dim
  60. def _embed(self, text: str) -> List[float]:
  61. vector = [0.0] * self.dim
  62. tokens = re.findall(r"[\w\u4e00-\u9fff]+", text.lower())
  63. if not tokens:
  64. tokens = [text]
  65. for token in tokens:
  66. digest = hashlib.sha256(token.encode("utf-8")).digest()
  67. index = int.from_bytes(digest[:4], "big") % self.dim
  68. sign = 1.0 if digest[4] % 2 == 0 else -1.0
  69. vector[index] += sign
  70. norm = math.sqrt(sum(x * x for x in vector)) or 1.0
  71. return [x / norm for x in vector]
  72. def embed_query(self, text: str) -> List[float]:
  73. return self._embed(text)
  74. def embed_documents(self, texts: Iterable[str]) -> List[List[float]]:
  75. return [self._embed(text) for text in texts]
  76. def get_embeddings():
  77. provider = env_value("EMBEDDING_PROVIDER", default="hash").lower()
  78. if provider == "ollama":
  79. from langchain_ollama import OllamaEmbeddings
  80. return OllamaEmbeddings(
  81. model=env_value("OLLAMA_EMBEDDING_MODEL", default="mxbai-embed-large"),
  82. base_url=env_value("OLLAMA_BASE_URL", default="http://127.0.0.1:11434"),
  83. )
  84. return HashEmbeddings()
  85. def print_dependency_hint(error: ModuleNotFoundError) -> None:
  86. print(f"缺少依赖: {error.name}")
  87. print("可在 `代码` 目录执行: pip install -r requirements_2_tools.txt")