diff --git a/scripts/ai_agent/config/rag_config.json b/scripts/ai_agent/config/rag_config.json index ebbb150..d4e07f6 100644 --- a/scripts/ai_agent/config/rag_config.json +++ b/scripts/ai_agent/config/rag_config.json @@ -6,7 +6,7 @@ "collection_name":"drone_docs", "model_config_llamacpp": { - "n_ctx":512, + "n_ctx":40960, "n_threads":4, "n_gpu_layers":36, "n_seq_max":256, diff --git a/scripts/ai_agent/memory/knowledge_base/map/vector_store/osm_map1/47c25560-66ff-4ee3-85f6-badb1631102b/data_level0.bin b/scripts/ai_agent/memory/knowledge_base/map/vector_store/osm_map1/47c25560-66ff-4ee3-85f6-badb1631102b/data_level0.bin new file mode 100644 index 0000000..86568df Binary files /dev/null and b/scripts/ai_agent/memory/knowledge_base/map/vector_store/osm_map1/47c25560-66ff-4ee3-85f6-badb1631102b/data_level0.bin differ diff --git a/scripts/ai_agent/memory/knowledge_base/map/vector_store/osm_map1/47c25560-66ff-4ee3-85f6-badb1631102b/header.bin b/scripts/ai_agent/memory/knowledge_base/map/vector_store/osm_map1/47c25560-66ff-4ee3-85f6-badb1631102b/header.bin new file mode 100644 index 0000000..b6867c7 Binary files /dev/null and b/scripts/ai_agent/memory/knowledge_base/map/vector_store/osm_map1/47c25560-66ff-4ee3-85f6-badb1631102b/header.bin differ diff --git a/scripts/ai_agent/memory/knowledge_base/map/vector_store/osm_map1/47c25560-66ff-4ee3-85f6-badb1631102b/length.bin b/scripts/ai_agent/memory/knowledge_base/map/vector_store/osm_map1/47c25560-66ff-4ee3-85f6-badb1631102b/length.bin new file mode 100644 index 0000000..ba4322f Binary files /dev/null and b/scripts/ai_agent/memory/knowledge_base/map/vector_store/osm_map1/47c25560-66ff-4ee3-85f6-badb1631102b/length.bin differ diff --git a/scripts/ai_agent/memory/knowledge_base/map/vector_store/osm_map1/47c25560-66ff-4ee3-85f6-badb1631102b/link_lists.bin b/scripts/ai_agent/memory/knowledge_base/map/vector_store/osm_map1/47c25560-66ff-4ee3-85f6-badb1631102b/link_lists.bin new file mode 100644 index 0000000..e69de29 diff --git a/scripts/ai_agent/memory/knowledge_base/map/vector_store/osm_map1/chroma.sqlite3 b/scripts/ai_agent/memory/knowledge_base/map/vector_store/osm_map1/chroma.sqlite3 index b774f60..5de06b8 100644 Binary files a/scripts/ai_agent/memory/knowledge_base/map/vector_store/osm_map1/chroma.sqlite3 and b/scripts/ai_agent/memory/knowledge_base/map/vector_store/osm_map1/chroma.sqlite3 differ diff --git a/scripts/ai_agent/models/models_client.py b/scripts/ai_agent/models/models_client.py index acc7e89..715c0f6 100644 --- a/scripts/ai_agent/models/models_client.py +++ b/scripts/ai_agent/models/models_client.py @@ -213,6 +213,39 @@ class Models_Client: 返回: 包含推理结果的字典 """ + # # 处理图像 + # image_data = [] + + # if images: + # # for img in images: + # try: + # # image_data.append(PIL_image_to_base64(image=img)) + # image_data= images + # except Exception as e: + # return {"error": f"处理图像base64对象失败: {str(e)}"} + + # elif image_paths: + # for path in image_paths: + # try: + # image_data.append(PIL_image_to_base64(image_path=path)) + # except Exception as e: + # return {"error": f"处理图像 {path} 失败: {str(e)}"} + + + + # if not image_data: + # return {"error": "未提供有效的图像数据"} + + # payload = { + # "user_prompt": prompt, + # "image_data": image_data, + # "max_tokens": max_tokens, + # "temperature": temperature, + # "top_p": top_p, + # "system_prompt": system_prompt, + # "stop": stop + # } + try: # 将 Pydantic 模型转换为 JSON 字符串 if hasattr(request, 'model_dump_json'): diff --git a/scripts/ai_agent/models/models_server.py b/scripts/ai_agent/models/models_server.py index bf1de36..dabd388 100644 --- a/scripts/ai_agent/models/models_server.py +++ b/scripts/ai_agent/models/models_server.py @@ -818,7 +818,6 @@ def test_inference(inference_type=0): if __name__ == "__main__": - main() + # main() # test_inference(2) - # logger.info("work finish") - + logger.info("work finish") \ No newline at end of file diff --git a/scripts/ai_agent/tools/data_process/image_process/image_process.py b/scripts/ai_agent/tools/data_process/image_process/image_process.py index d98de6e..510ff68 100644 --- a/scripts/ai_agent/tools/data_process/image_process/image_process.py +++ b/scripts/ai_agent/tools/data_process/image_process/image_process.py @@ -85,7 +85,90 @@ def PIL_image_to_base64( image_path: Optional[str] = None, image: Optional[PIL_I image.save(buffered, format="JPEG", quality=90) return base64.b64encode(buffered.getvalue()).decode('utf-8') -# Removed ROS specific functions (ros_image2pil_image, ros_image2dict) as they depend on rospy/cv_bridge +# def ros_image2pil_image(self, ros_image_msg:Sensor_Image,supported_image_formats): +# """回调函数:将ROS Image转为PIL Image并处理""" +# try: +# bridge_cv = CvBridge() +# # 1. 将ROS Image消息转为OpenCV格式(默认BGR8编码) +# # 若图像编码不同(如rgb8),需指定格式:bridge.imgmsg_to_cv2(ros_image_msg, "rgb8") +# # 尝试转换为OpenCV格式 +# if ros_image_msg.encoding in supported_image_formats: +# cv_image = bridge_cv.imgmsg_to_cv2(ros_image_msg, desired_encoding=ros_image_msg.encoding) +# else: +# # 尝试默认转换 +# cv_image = bridge_cv.imgmsg_to_cv2(ros_image_msg) +# logger.warning(f"转换不支持的图像编码: {ros_image_msg.encoding}") + + +# # 2. OpenCV默认是BGR格式,转为PIL需要的RGB格式 +# rgb_image = cv2.cvtColor(cv_image, cv2.COLOR_BGR2RGB) + +# # 3. 转为PIL Image格式 +# pil_image = PIL_Image.fromarray(rgb_image) + +# # 此处可添加对PIL Image的处理(如显示、保存等) +# rospy.loginfo(f"转换成功:PIL Image尺寸 {pil_image.size}") +# return pil_image +# # 示例:显示图像(需要PIL的显示支持) +# # pil_image.show() + +# except CvBridgeError as e: +# rospy.logerr(f"转换失败:{e}") +# except Exception as e: +# rospy.logerr(f"处理错误:{e}") + + +# def ros_image2dict(self, image_msg: Sensor_Image, +# supported_image_formats=['bgr8', 'rgb8', 'mono8'], +# max_dim:int =2000) : +# """ +# 将ROS图像消息转换为字典格式,便于在上下文中存储 + +# 参数: +# image_msg: ROS的Image消息 + +# 返回: +# 包含图像信息的字典,或None(转换失败时) +# """ +# try: +# # 尝试转换为OpenCV格式 +# if image_msg.encoding in self.supported_image_formats: +# cv_image = self.bridge.imgmsg_to_cv2(image_msg, desired_encoding=image_msg.encoding) +# else: +# # 尝试默认转换 +# cv_image = self.bridge.imgmsg_to_cv2(image_msg) +# logger.warning(f"转换不支持的图像编码: {image_msg.encoding}") + +# # 图像预处理:调整大小以减少数据量 +# h, w = cv_image.shape[:2] +# if max(h, w) > max_dim: +# scale = max_dim / max(h, w) +# cv_image = cv2.resize( +# cv_image, +# (int(w * scale), int(h * scale)), +# interpolation=cv2.INTER_AREA +# ) + +# # 转换为JPEG并编码为base64 +# encode_param = [int(cv2.IMWRITE_JPEG_QUALITY), 80] +# _, buffer = cv2.imencode('.jpg', cv_image, encode_param) +# img_base64 = base64.b64encode(buffer).decode('utf-8') + +# return { +# "type": "image", +# "format": "jpg", +# "data": img_base64, +# "width": cv_image.shape[1], +# "height": cv_image.shape[0], +# "original_encoding": image_msg.encoding, +# "timestamp": image_msg.header.stamp.to_sec() +# } + +# except CvBridgeError as e: +# logger.error(f"CV桥接错误: {str(e)}") +# except Exception as e: +# logger.error(f"图像处理错误: {str(e)}") +# return None def PIL_image_to_base64_sizelmt(image_path:Optional[str]=None,image:Optional[PIL_Image.Image] = None, need_size_lmt:bool= False, max_size:tuple=(800, 800), quality:float=90): diff --git a/scripts/ai_agent/tools/memory_mag/rag/rag.py b/scripts/ai_agent/tools/memory_mag/rag/rag.py index da053cf..77a2241 100644 --- a/scripts/ai_agent/tools/memory_mag/rag/rag.py +++ b/scripts/ai_agent/tools/memory_mag/rag/rag.py @@ -101,16 +101,15 @@ def set_embeddings(embedding_model_path, model_config:Optional[dict[str,Any]]): if "llamacpp_embeddings" == embedding_type: - # 使用 .get() 方法提供默认值,确保即使配置文件中缺少某些字段也能正常工作 embeddings = set_embeddings_llamacpp( model_path=embedding_model_path, - n_ctx=model_config.get("n_ctx", 512), - n_threads=model_config.get("n_threads", 4), - n_gpu_layers=model_config.get("n_gpu_layers", 0), # RTX 5090建议设20,充分利用GPU - n_seq_max=model_config.get("n_seq_max", 128), - n_threads_batch=model_config.get("n_threads_batch", 4), - flash_attn=model_config.get("flash_attn", True), - verbose=model_config.get("verbose", False) + n_ctx=model_config["n_ctx"], + n_threads=model_config["n_threads"], + n_gpu_layers=model_config["n_gpu_layers"], # RTX 5090建议设20,充分利用GPU + n_seq_max=model_config["n_seq_max"], + n_threads_batch = model_config["n_threads_batch"], + flash_attn = model_config["flash_attn"], + verbose=model_config["verbose"] ) elif "huggingFace_embeddings" == embedding_type: embeddings = set_embeddings_huggingFace( @@ -157,49 +156,19 @@ def load_vector_database(embeddings, collection_name:str): """加载已存在的向量数据库""" try: - if not os.path.exists(path=persist_directory): - logger.warning(f"向量数据库目录不存在: {persist_directory}") + if os.path.exists(path=persist_directory): + vector_db = Chroma( + persist_directory=persist_directory, + embedding_function=embeddings, + collection_name=collection_name + ) + print(f"已加载向量数据库 from {persist_directory}") + + return vector_db + else: return None - - # 先检查集合是否存在 - try: - import chromadb - client = chromadb.PersistentClient(path=persist_directory) - collections = client.list_collections() - collection_names = [col.name for col in collections] - - if collection_name not in collection_names: - logger.warning(f"集合 '{collection_name}' 不存在于数据库中。") - logger.info(f"可用的集合: {collection_names}") - # 尝试查找有数据的集合 - for col in collections: - if col.count() > 0: - logger.info(f"发现非空集合: {col.name} (count: {col.count()})") - return None - - # 检查集合是否有数据 - target_collection = client.get_collection(name=collection_name) - doc_count = target_collection.count() - if doc_count == 0: - logger.warning(f"集合 '{collection_name}' 存在但为空 (count: 0)") - logger.warning(f"⚠️ 该集合没有数据,RAG 检索将返回空结果") - # 仍然返回数据库对象,允许后续操作(如添加数据) - else: - logger.info(f"✅ 集合 '{collection_name}' 包含 {doc_count} 条文档") - except Exception as check_error: - logger.warning(f"检查集合时出错: {check_error},继续尝试加载...") - - # 加载向量数据库 - vector_db = Chroma( - persist_directory=persist_directory, - embedding_function=embeddings, - collection_name=collection_name - ) - logger.info(f"✅ 成功加载向量数据库 from {persist_directory}, 集合: {collection_name}") - return vector_db - except Exception as e: - logger.error(f"vector_database加载失败: {str(e)}", exc_info=True) + logger.error(f"vector_database加载失败: {str(e)}") return None #设置文本分割器 @@ -237,7 +206,7 @@ def set_document_loaders(self): def retrieve_relevant_info(vectorstore, query: str, k: int = 3, - score_threshold: float = None + score_threshold: float = 0.2 ) -> List[Dict[str, Any]]: """ 检索与查询相关的信息 @@ -245,8 +214,7 @@ def retrieve_relevant_info(vectorstore, 参数: query: 查询文本 k: 最多返回的结果数量 - score_threshold: 相关性分数阈值。如果为 None,则使用自适应阈值(前 k 个结果中最高分数的 1.5 倍) - 对于 L2 距离,分数越小越相似,阈值应该是一个较大的值 + score_threshold: 相关性分数阈值 返回: 包含相关文档内容和分数的列表 @@ -255,41 +223,21 @@ def retrieve_relevant_info(vectorstore, # 执行相似性搜索,返回带分数的结果 docs_and_scores = vectorstore.similarity_search_with_score(query, k=k) - if not docs_and_scores: - logger.info(f"检索到 0 条结果 (k={k})") - return [] - - # 如果没有指定阈值,使用自适应阈值 - # 对于 L2 距离,取前 k 个结果中最高的分数,然后乘以一个系数作为阈值 - if score_threshold is None: - max_score = max(score for _, score in docs_and_scores) - # 使用最高分数的 1.5 倍作为阈值,确保包含所有前 k 个结果 - score_threshold = max_score * 1.5 - logger.debug(f"自适应阈值: {score_threshold:.2f} (基于最高分数 {max_score:.2f})") - # 过滤并格式化结果 results = [] for doc, score in docs_and_scores: - # 对于 L2 距离,分数越小越相似 - # 如果阈值很大(> 1000),说明是 L2 距离,使用 < 比较 - # 如果阈值很小(< 1),说明可能是余弦距离,使用 < 比较 - if score < score_threshold: + if score < score_threshold: # 分数越低表示越相似 results.append({ "content": doc.page_content, "metadata": doc.metadata, "similarity_score": float(score) }) - else: - logger.debug(f"文档因分数 {score:.2f} >= 阈值 {score_threshold:.2f} 被过滤") - threshold_str = f"{score_threshold:.2f}" if score_threshold is not None else "自适应" - logger.info(f"检索到 {len(results)} 条相关信息 (k={k}, 阈值={threshold_str})") - if results: - logger.debug(f"相似度分数范围: {min(r['similarity_score'] for r in results):.2f} - {max(r['similarity_score'] for r in results):.2f}") + logger.info(f"检索到 {len(results)} 条相关信息 (k={k}, 阈值={score_threshold})") return results except Exception as e: - logger.error(f"检索相关信息失败: {str(e)}", exc_info=True) + logger.error(f"检索相关信息失败: {str(e)}") return [] def get_retriever(vectorstore,search_kwargs: Dict[str, Any] = None) -> Any: