1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
   | import json from typing import List,Union,Optional
  import chromadb import pandas as pd from chromadb.config import Settings from chromadb.utils import embedding_functions import hashlib import uuid from chromadb.api.types import IDs,OneOrMany,Document
 
  default_ef = embedding_functions.DefaultEmbeddingFunction()
  def deterministic_uuid(content: Union[str, bytes]) -> str:     """     根据输入内容的 SHA-256 哈希生成确定性的 UUID。     :param content: `deterministic_uuid` 函数中的 `content` 参数可以是字符串或字节数据类型。     :type content: Union[str, bytes]     :return: 以字符串形式返回 UUID(通用唯一标识符)。     """     if isinstance(content, str):         content_bytes = content.encode("utf-8")     elif isinstance(content, bytes):         content_bytes = content     else:         raise ValueError(f"Content type {type(content)} not supported !")     hash_object = hashlib.sha256(content_bytes)     hash_hex = hash_object.hexdigest()     namespace = uuid.UUID("00000000-0000-0000-0000-000000000000")     content_uuid = str(uuid.uuid5(namespace, hash_hex))     return content_uuid
 
 
 
  class ChromaDB_VectorStore():     def __init__(self, config=None):         if config is None:             config = {}
          path = config.get("path", "CHROMADB")          self.embedding_function = config.get("embedding_function", default_ef)          curr_client = config.get("client", "persistent")          collection_metadata = config.get("collection_metadata", None)          self.n_results = config.get("n_result", 10)          self.collection_name = config.get("collection","documentation")          if curr_client == "persistent":             self.chroma_client = chromadb.PersistentClient(                 path=path, settings=Settings(anonymized_telemetry=False)             )         elif curr_client == "in-memory":             self.chroma_client = chromadb.EphemeralClient(                 settings=Settings(anonymized_telemetry=False)             )         elif isinstance(curr_client, chromadb.api.client.Client):              self.chroma_client = curr_client         else:             raise ValueError(f"在配置中设置了不支持的客户端: {curr_client}")
          self.collection = self.chroma_client.get_or_create_collection(             name=self.collection_name,             embedding_function=self.embedding_function,             metadata=collection_metadata,         )
      def generate_embedding(self, data: str, **kwargs) -> List[float]:         """         接受字符串输入,使用指定函数生成嵌入,并将嵌入作为浮点数列表返回。                  :param data: `generate_embedding` 函数中的 `data` 参数是一个字符串,表示要生成嵌入的输入数据。         :type data: str         :return: 如果 `embedding` 列表的长度为 1,则该函数将返回列表的第一个元素。否则,它将返回整个 `embedding` 列表。         """         embedding = self.embedding_function([data])         if len(embedding) == 1:             return embedding[0]         return embedding
      def add_documentation(self, documentation: str, **kwargs) -> str:         """         将文档及其相应的嵌入添加到集合中并返回生成的 ID。                  :param documentation: `add_documentation` 方法接受一个 `documentation` 参数,该参数是包含要添加的文档的字符串。此方法还接受其他关键字参数         (**kwargs) 以提高灵活性。         :type documentation: str         :return: 返回添加到集合中的文档的 `id`。         """         id = deterministic_uuid(documentation)         self.collection.add(             documents=documentation,             embeddings=self.generate_embedding(documentation),             ids=id,         )         return id
      def get_training_data(self, **kwargs) -> pd.DataFrame:         collection_data = self.collection.get()         df = pd.DataFrame()         if collection_data is not None:             documents = [doc for doc in collection_data["documents"]]             ids = collection_data["ids"]             df_doc = pd.DataFrame({"id": ids,                                    "question": [None for doc in documents],                                    "content": [doc for doc in documents]}                                   )             df_doc["training_data_type"] = self.collection_name             df = pd.concat([df, df_doc])         return df
      def remove_training_data(self, id: IDs, **kwargs) -> bool:         """         根据提供的 ID 从集合中删除训练数据。         :param id: `remove_training_data` 方法中的 `id` 参数为 `IDs` 类型。它用于指定需要从集合中移除的训练数据的标识符。         :type id: IDs         :return: 返回一个布尔值。如果成功删除了指定 ID 的训练数据,则返回 `True`;如果删除过程中出现错误,则返回 `False`。         """         try:             self.collection.delete(ids=id)             return True         except:             return False
      def remove_collection(self) -> bool:         """         尝试删除一个集合并在必要时重新创建它,如果成功则返回 True,否则返回 False。         :return: `remove_collection` 方法返回一个布尔值 - 如果集合被成功删除并重新创建,则返回 `True`;如果在此过程中发生异常,则返回 `False`。         """         try:             self.chroma_client.delete_collection(name=self.collection_name)             self.collection = self.chroma_client.get_or_create_collection(                     name=self.collection_name, embedding_function=self.embedding_function                 )             return True         except:             return False
      @staticmethod     def _extract_documents(query_results,collection_name) -> list:          """         该函数从查询结果中提取文档,处理文档嵌套在列表中的情况。                  :param query_results:         您提供的代码片段似乎是一个名为“_extract_documents”的函数,它以“query_results”作为参数,并应该返回从查询结果中提取的文档列表。但是,代码片段中有几个问题需要解决:         :return: 变量“document”,但 return 语句似乎有拼写错误。应该是“return documents”,而不是“return document”。         """         if query_results is None:             return []
          if "documents" in query_results:             documents = query_results["documents"]             if len(documents) == 1 and isinstance(documents[0], list):                 try:                     documents = [json.loads(doc) for doc in documents[0]]                 except Exception as e:                     return documents[0]             return documents
      def get_related(self, question: Optional[OneOrMany[Document]], **kwargs) -> list:         """         使用给定的问题查询集合并返回相关文档的列表。                  :param question: `get_related` 方法中的 `question` 参数属于 `Optional[OneOrMany[Document]]` 类型。这意味着它可以接受单个         `Document` 对象或 `Document` 对象集合,也可以为 `None`。         :type question: Optional[OneOrMany[Document]]         :return: 返回文件清单。         """         res = self.collection.query(query_texts=question,n_results=self.n_results)         return ChromaDB_VectorStore._extract_documents(res,self.collection_name)      if __name__ == "__main__":     config = {"path":"",               "embedding_function":"",               "client":object,               "collection_metadata":None,               "n_result":10,               "collection":"doc"}
 
   |