选二改吧from langchain_community.vectorstores import FAISS from langchain_huggingface import HuggingFaceEmbeddings from langchain_core.documents import Document from langchain.chains import ConversationalRetrievalChain from langchain.prompts import PromptTemplate from langchain_community.llms import HuggingFacePipeline import torch from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline from langchain.memory import ConversationBufferMemory # ========== 1. 加载嵌入模型 ========== embeddings = HuggingFaceEmbeddings( model_name=r"C:\Users\Lenovo\rag_scrapydb\src\local_embeddings_cache\all-MiniLM-L6-v2" ) # ========== 2. 加载 FAISS 向量库 ========== VECTOR_STORE_PATH = r"C:\Users\Lenovo\rag_scrapydb\src\my_vectorstore" vectorstore = FAISS.load_local(VECTOR_STORE_PATH, embeddings=embeddings, allow_dangerous_deserialization=True) retriever = vectorstore.as_retriever(search_kwargs={"k": 3}) # 检索 top-3 文档 # ========== 3. 加载本地 LLM(以 ChatGLM 为例)========== model_path = r"C:\Users\Lenovo\rag_scrapydb\local_embeddings_cache\all-MiniLM-L6-v2" # 修改为你自己的模型路径 tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=True) model = AutoModelForCausalLM.from_pretrained(model_path, trust_remote_code=True).half().cuda() pipe = pipeline( "text-generation", model=model, tokenizer=tokenizer, max_new_tokens=200, device=0, pad_token_id=tokenizer.eos_token_id # 避免警告 ) llm = HuggingFacePipeline(pipeline=pipe) # ========== 4. 定义 Prompt Template ========== prompt_template = """请基于以下提供的背景信息,回答用户的问题。如果无法找到相关信息,请说明原因。 历史对话: {chat_history} 背景信息: {context} 问题: {question} 请确保回答简洁清晰,并在回答末尾列出引用来源(网址)。 """ PROMPT = PromptTemplate( template=prompt_template, input_variables=["context", "question", "chat_history"] ) # ========== 5. 创建带记忆的 RAG Chain ========== memory = ConversationBufferMemory(memory_key="chat_history", input_key="question") qa_chain = ConversationalRetrievalChain.from_llm( llm=llm, retriever=retriever, combine_docs_chain_kwargs={"prompt": PROMPT}, memory=memory ) # ========== 6. 运行聊天交互 ========== def chat(): print("开始与 RAG 系统对话吧!输入 '退出' 结束程序。") while True: user_input = input("你:") if user_input.lower() in ['退出', 'exit', 'q']: break result = qa_chain.invoke({"question": user_input}) answer = result["answer"] # 提取引用链接 sources = set(doc.metadata.get('source', '') for doc in result["source_documents"] if doc.metadata.get('source')) source_str = "\n".join([f"[{i+1}] {s}" for i, s in enumerate(sources)]) print(f"助手:{answer}\n\n参考链接:\n{source_str}") if __name__ == "__main__": chat()

时间: 2025-08-31 16:19:04 AIGC 浏览: 23
你当前的代码中存在两个关键问题: --- ## ❌ 问题一:错误地将 Embedding 模型路径用作 LLM 模型 ```python model_path = r"C:\Users\Lenovo\rag_scrapydb\src\local_embeddings_cache\all-MiniLM-L6-v2" ``` 你使用的是 **Sentence-BERT 类的嵌入模型**(`all-MiniLM-L6-v2`),它不能用于生成回答(LLM)。这类模型是为 FAISS 向量化检索服务的,不能作为语言模型进行文本生成。 --- ## ❌ 问题二:`.half().cuda()` 导致 CUDA 错误 你尝试调用 `.cuda()`,但你的 PyTorch 不支持 CUDA,导致如下报错: ``` AssertionError: Torch not compiled with CUDA enabled ``` --- ## ✅ 解决方案:只修改与 LLM 相关的部分(选二改) 我们保留你的 embedding、FAISS 和 prompt 部分不变,**只修改 LLM 加载部分**。以下是修正后的完整代码段: --- ## ✅ 改进后的 LLM 加载方式(使用 CPU + 本地 ChatGLM-6B) ### 前提条件: 你需要下载 `chatglm-6b` 模型,并将其放在以下路径(或你自己指定): ``` C:\models\chatglm-6b ``` 该目录应包含: ``` chatglm-6b/ ├── config.json ├── pytorch_model.bin ├── tokenizer_config.json ├── vocab.txt └── ...其他文件 ``` 如果你还没有这个模型,请先下载(见最后相关问题)。 --- ## ✅ 修改后的代码段(替换原第3部分) ```python # ========== 3. 加载本地 LLM(以 ChatGLM-6B 为例)========== model_path = r"C:\models\chatglm-6b" # 替换为你自己的 ChatGLM 模型路径 # 如果你没有 GPU,可以去掉 .half().cuda() tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=True) # 使用 CPU 加载模型 model = AutoModelForCausalLM.from_pretrained(model_path, trust_remote_code=True) pipe = pipeline( "text-generation", model=model, tokenizer=tokenizer, max_new_tokens=200, device=-1, # 强制使用 CPU pad_token_id=tokenizer.eos_token_id ) llm = HuggingFacePipeline(pipeline=pipe) ``` --- ## 🧠 说明: | 参数 | 说明 | |------|------| | `device=-1` | 表示使用 CPU | | `max_new_tokens=200` | 控制输出长度 | | `pad_token_id=tokenizer.eos_token_id` | 避免警告信息 | --- ## ✅ 完整流程图 ``` 用户输入 → 检索器从 FAISS 中查找 top-3 文档 → 结合历史对话和背景信息 → 交给 LLM 回答 → 输出答案 + 来源链接 ``` --- ## ✅ 测试运行结果示例 ``` 开始与 RAG 系统对话吧!输入 '退出' 结束程序。 你:什么是量子计算? 助手:量子计算是一种利用量子比特(qubit)进行计算的方法,能够并行处理大量数据... 参考链接: [1] https://example.com/quantum-computing-intro [2] https://example.com/quantum-bits ``` --- ## ✅ 总结 | 原因 | 解决方法 | |------|----------| | 使用了 embedding 模型作为 LLM | 改用真正的 LLM 模型(如 ChatGLM-6B) | | 缺少 CUDA 支持 | 改用 CPU 模式加载模型(`device=-1`) | | 没有正确设置 tokenizer | 设置 `pad_token_id=tokenizer.eos_token_id` 避免警告 | --- ###
阅读全文

相关推荐

from langchain_community.vectorstores import FAISS from langchain_huggingface import HuggingFaceEmbeddings from langchain_core.documents import Document from langchain.chains import ConversationalRetrievalChain from langchain.prompts import PromptTemplate from langchain_community.llms import HuggingFacePipeline import torch from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline from langchain.memory import ConversationBufferMemory ========== 1. 加载嵌入模型 ========== embeddings = HuggingFaceEmbeddings( model_name=r"C:\Users\Lenovo\rag_scrapydb\src\local_embeddings_cache\all-MiniLM-L6-v2" ) ========== 2. 加载 FAISS 向量库 ========== VECTOR_STORE_PATH = r"C:\Users\Lenovo\rag_scrapydb\src\my_vectorstore" vectorstore = FAISS.load_local(VECTOR_STORE_PATH, embeddings=embeddings, allow_dangerous_deserialization=True) retriever = vectorstore.as_retriever(search_kwargs={“k”: 3}) # 检索 top-3 文档 ========== 3. 加载本地 LLM(以 ChatGLM 为例)========== model_path = r"C:\Users\Lenovo\rag_scrapydb\local_embeddings_cache\all-MiniLM-L6-v2" # 修改为你自己的模型路径 tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=True) model = AutoModelForCausalLM.from_pretrained(model_path, trust_remote_code=True).half().cuda() pipe = pipeline( “text-generation”, model=model, tokenizer=tokenizer, max_new_tokens=200, device=0, pad_token_id=tokenizer.eos_token_id # 避免警告 ) llm = HuggingFacePipeline(pipeline=pipe) ========== 4. 定义 Prompt Template ========== prompt_template = “”"请基于以下提供的背景信息,回答用户的问题。如果无法找到相关信息,请说明原因。 历史对话: 背景信息: 问题: 请确保回答简洁清晰,并在回答末尾列出引用来源(网址)。 “”" PROMPT = PromptTemplate( template=prompt_template, input_variables=[“context”, “question”, “chat_history”] ) ========== 5. 创建带记忆的 RAG Chain ========== memory = ConversationBufferMemory(memory_key=“chat_history”, input_key=“question”) qa_chain = ConversationalRetrievalChain.from_llm( llm=llm, retriever=retriever, combine_docs_chain_kwargs={“prompt”: PROMPT}, memory=memory ) ========== 6. 运行聊天交互 ========== def chat(): print(“开始与 RAG 系统对话吧!输入 ‘退出’ 结束程序。”) while True: user_input = input(“你:”) if user_input.lower() in [‘退出’, ‘exit’, ‘q’]: break result = qa_chain.invoke({"question": user_input}) answer = result["answer"] # 提取引用链接 sources = set(doc.metadata.get('source', '') for doc in result["source_documents"] if doc.metadata.get('source')) source_str = "\n".join([f"[{i+1}] {s}" for i, s in enumerate(sources)]) print(f"助手:{answer}\n\n参考链接:\n{source_str}") if name == “main”: chat() 下完了,给我改一下吧,要完整的

✅ 方法一:加载模型时自动识别正确的 tokenizer from langchain_community.vectorstores import FAISS from langchain_huggingface import HuggingFaceEmbeddings from langchain_core.documents import Document from langchain.chains import ConversationalRetrievalChain from langchain.prompts import PromptTemplate from langchain_community.llms import HuggingFacePipeline import torch from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline from langchain.memory import ConversationBufferMemory # ========== 1. 加载嵌入模型 ========== embeddings = HuggingFaceEmbeddings( model_name=r"C:\Users\Lenovo\rag_scrapydb\src\local_embeddings_cache\all-MiniLM-L6-v2" ) # ========== 2. 加载 FAISS 向量库 ========== VECTOR_STORE_PATH = r"C:\Users\Lenovo\rag_scrapydb\src\my_vectorstore" vectorstore = FAISS.load_local(VECTOR_STORE_PATH, embeddings=embeddings, allow_dangerous_deserialization=True) retriever = vectorstore.as_retriever(search_kwargs={"k": 3}) # 检索 top-3 文档 # ========== 3. 加载本地 LLM(以 ChatGLM 为例)========== model_path = r"C:\models\chatglm-6b" # 修改为你自己的模型路径 tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=True) model = AutoModelForCausalLM.from_pretrained(model_path, trust_remote_code=True).half().cuda() pipe = pipeline( "text-generation", model=model, tokenizer=tokenizer, max_new_tokens=200, device=0, pad_token_id=tokenizer.eos_token_id # 避免警告 ) llm = HuggingFacePipeline(pipeline=pipe) # ========== 4. 定义 Prompt Template ========== prompt_template = """请基于以下提供的背景信息,回答用户的问题。如果无法找到相关信息,请说明原因。 历史对话: {chat_history} 背景信息: {context} 问题: {question} 请确保回答简洁清晰,并在回答末尾列出引用来源(网址)。 """ PROMPT = PromptTemplate( template=prompt_template, input_variables=["context", "question", "chat_history"] ) # ========== 5. 创建带记忆的 RAG Chain ========== memory = ConversationBufferMemory(memory_key="chat_history", input_key="question") qa_chain = ConversationalRetrievalChain.from_llm( llm=llm, retriever=retriever, combine_docs_chain_kwargs={"prompt": PROMPT}, memory=memory ) # ========== 6. 运行聊天交互 ========== def chat(): print("开始与 RAG 系统对话吧!输入 '退出' 结束程序。") while True: user_input = input("你:") if user_input.lower() in ['退出', 'exit', 'q']: break result = qa_chain.invoke({"question": user_input}) answer = result["answer"] # 提取引用链接 sources = set(doc.metadata.get('source', '') for doc in result["source_documents"] if doc.metadata.get('source')) source_str = "\n".join([f"[{i+1}] {s}" for i, s in enumerate(sources)]) print(f"助手:{answer}\n\n参考链接:\n{source_str}") if __name__ == "__main__": chat() 改吧,要完整代码

我正在编辑【python】代码,遇到了 【Traceback (most recent call last): File "D:\python\python3.11.5\Lib\site-packages\langchain\_api\module_import.py", line 69, in import_by_name module = importlib.import_module(new_module) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "D:\python\python3.11.5\Lib\importlib\__init__.py", line 126, in import_module return _bootstrap._gcd_import(name[level:], package, level) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "<frozen importlib._bootstrap>", line 1204, in _gcd_import File "<frozen importlib._bootstrap>", line 1176, in _find_and_load File "<frozen importlib._bootstrap>", line 1126, in _find_and_load_unlocked File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed File "<frozen importlib._bootstrap>", line 1204, in _gcd_import File "<frozen importlib._bootstrap>", line 1176, in _find_and_load File "<frozen importlib._bootstrap>", line 1140, in _find_and_load_unlocked ModuleNotFoundError: No module named 'langchain_community' The above exception was the direct cause of the following exception: Traceback (most recent call last): File "D:\code\nepu_spider\rag\rag_sys.py", line 11, in <module> from langchain.embeddings import HuggingFaceEmbeddings File "D:\python\python3.11.5\Lib\site-packages\langchain\embeddings\__init__.py", line 167, in __getattr__ return _import_attribute(name) ^^^^^^^^^^^^^^^^^^^^^^^ File "D:\python\python3.11.5\Lib\site-packages\langchain\_api\module_import.py", line 72, in import_by_name raise ModuleNotFoundError( ModuleNotFoundError: Module langchain_community.embeddings not found. Please install langchain-community to access this module. You can install it using pip install -U langchain-community 】 ,请帮我检查并改正错误点。我的原始代码如下: 【import os import json import pickle from langchain_core.language_models import LLM import install_faiss import numpy as np import requests from langchain.text_splitter import RecursiveCharacterTextSplitter from langchain.embeddings import HuggingFaceEmbeddings from langchain.vectorstores import FAISS from langchain.chains import RetrievalQA from langchain.prompts import PromptTemplate from langchain.llms import OpenAI from langchain.docstore.document import Document from typing import List, Dict, Any, Tuple, Optional # 自定义智谱AI的LangChain包装器 class ZhipuAILLM(LLM): def __init__(self, api_key: str, model: str = "glm-4", temperature: float = 0.7, zhipuai=None): """初始化智谱AI模型""" self.api_key = api_key self.model = model self.temperature = temperature zhipuai.api_key = api_key # 设置API密钥 def _call(self, prompt: str, stop: Optional[List[str]] = None, zhipuai=None) -> str: """调用智谱AI API生成文本""" try: response = zhipuai.model_api.invoke( model=self.model, prompt=[{"role": "user", "content": prompt}], temperature=self.temperature, top_p=0.7, ) if response["code"] == 200: return response["data"]["choices"][0]["content"] else: raise ValueError(f"智谱AI API错误: {response['msg']}") except Exception as e: raise RuntimeError(f"调用智谱AI失败: {str(e)}") @property def _llm_type(self) -> str: return "zhipuai" class RAGSystem: def __init__(self, config: Dict[str, Any]): """初始化RAG系统""" self.config = config self.embedding_model = self._load_embedding_model() self.llm = self._load_llm() self.vector_db = None self.doc_id_map = {} # 自动加载或创建索引 self._initialize_index() def _load_embedding_model(self) -> HuggingFaceEmbeddings: """加载嵌入模型""" model_name = self.config.get("embedding_model", "sentence-transformers/all-mpnet-base-v2") return HuggingFaceEmbeddings( model_name=model_name, model_kwargs={"device": self.config.get("embedding_device", "cpu")} ) def _load_llm(self): """加载大语言模型 - 使用智谱AI""" llm_provider = self.config.get("llm_provider", "zhipuai") if llm_provider == "zhipuai": return ZhipuAILLM( api_key=self.config["zhipuai_api_key"], # 使用智谱AI密钥 model=self.config.get("llm_model", "glm-4"), temperature=self.config.get("temperature", 0.7) ) elif llm_provider == "openai": # 保留OpenAI支持 from langchain.llms import OpenAI return OpenAI( api_key=self.config["openai_api_key"], model_name=self.config.get("llm_model", "gpt-3.5-turbo"), temperature=self.config.get("temperature", 0.7) ) else: raise ValueError(f"不支持的LLM提供者: {llm_provider}") def _initialize_index(self): """初始化索引:加载现有或创建新索引""" index_path = self.config["index_path"] if os.path.exists(index_path): print(f"加载现有索引: {index_path}") self._load_vector_index() else: print(f"创建新索引: {index_path}") self._create_new_index() def _create_new_index(self): """创建新索引""" data_dir = self.config["data_dir"] if not os.path.exists(data_dir): print(f"数据目录不存在: {data_dir}") if self.config.get("auto_download", False): self._download_sample_data() else: raise FileNotFoundError(f"数据目录不存在: {data_dir}") documents = self._load_and_process_documents() self._create_vector_index(documents) def _download_sample_data(self): """下载示例数据""" print("下载示例数据...") data_dir = self.config["data_dir"] os.makedirs(data_dir, exist_ok=True) sample_urls = [ "https://raw.githubusercontent.com/langchain-ai/langchain/master/docs/docs_skeleton.json" ] for url in sample_urls: response = requests.get(url) filename = os.path.basename(url) file_path = os.path.join(data_dir, filename) with open(file_path, "wb") as f: f.write(response.content) print(f"下载完成: {filename}") def _load_and_process_documents(self) -> List[Document]: """加载并处理文档""" documents = [] data_dir = self.config["data_dir"] # 支持多种文件格式 for filename in os.listdir(data_dir): file_path = os.path.join(data_dir, filename) if filename.endswith(".json") or filename.endswith(".jsonl"): documents.extend(self._load_json_documents(file_path)) elif filename.endswith(".txt"): documents.extend(self._load_text_documents(file_path)) if not documents: raise ValueError(f"在 {data_dir} 中没有找到可处理的文档") # 文本分块 return self._split_documents(documents) def _load_json_documents(self, file_path: str) -> List[Document]: """加载JSON或JSONL文档""" documents = [] with open(file_path, "r") as f: if file_path.endswith(".jsonl"): # 处理JSONL文件 for line in f: try: data = json.loads(line) doc = self._create_document_from_data(data) documents.append(doc) except json.JSONDecodeError: print(f"跳过无效的JSON行: {line.strip()}") else: # 处理JSON文件 try: data = json.load(f) if isinstance(data, list): for item in data: doc = self._create_document_from_data(item) documents.append(doc) elif isinstance(data, dict): doc = self._create_document_from_data(data) documents.append(doc) except json.JSONDecodeError: print(f"无效的JSON文件: {file_path}") return documents def _load_text_documents(self, file_path: str) -> List[Document]: """加载纯文本文档""" with open(file_path, "r", encoding="utf-8") as f: content = f.read() return [Document( page_content=content, metadata={ "source": file_path, "title": os.path.basename(file_path), "category": "text" } )] def _create_document_from_data(self, data: Dict) -> Document: """从数据创建文档对象""" return Document( page_content=data.get("content", data.get("text", "")), metadata={ "source": data.get("url", data.get("source", "")), "title": data.get("title", ""), "category": data.get("category", "unknown"), "timestamp": data.get("timestamp", "") } ) def _split_documents(self, documents: List[Document]) -> List[Document]: """分割文档为块""" text_splitter = RecursiveCharacterTextSplitter( chunk_size=self.config.get("chunk_size", 1000), chunk_overlap=self.config.get("chunk_overlap", 200), length_function=len ) return text_splitter.split_documents(documents) def _create_vector_index(self, documents: List[Document]): """创建FAISS向量索引""" # 创建向量数据库 self.vector_db = FAISS.from_documents( documents=documents, embedding=self.embedding_model ) # 保存索引 os.makedirs(os.path.dirname(self.config["index_path"]), exist_ok=True) self.vector_db.save_local(self.config["index_path"]) # 创建文档ID映射 for idx, doc in enumerate(documents): self.doc_id_map[idx] = { "source": doc.metadata["source"], "title": doc.metadata["title"], "category": doc.metadata["category"] } # 保存映射表 map_path = os.path.join(os.path.dirname(self.config["index_path"]), "doc_id_map.pkl") with open(map_path, "wb") as f: pickle.dump(self.doc_id_map, f) print(f"✅ 向量索引已创建并保存至 {self.config['index_path']}") def _load_vector_index(self): """加载现有的FAISS向量索引""" index_path = self.config["index_path"] # 加载向量数据库 self.vector_db = FAISS.load_local( folder_path=index_path, embeddings=self.embedding_model ) # 加载文档映射表 map_path = os.path.join(os.path.dirname(index_path), "doc_id_map.pkl") if os.path.exists(map_path): with open(map_path, "rb") as f: self.doc_id_map = pickle.load(f) print(f"✅ 文档映射表已加载") else: print("⚠️ 文档映射表未找到,将使用空映射") def ask_question(self, question: str, history: Optional[List] = None) -> Dict: """提问并获取答案""" if self.vector_db is None: raise ValueError("向量数据库未初始化") # 创建检索器 retriever = self.vector_db.as_retriever( search_kwargs={ "k": self.config.get("retrieval_top_k", 5), "score_threshold": self.config.get("score_threshold", 0.4) } ) # 创建问答链 qa_chain = self._create_qa_chain(retriever) # 执行问答 result = qa_chain({"query": question}) # 提取源文档 source_docs = result["source_documents"] doc_ids = [doc.metadata.get("doc_id", idx) for idx, doc in enumerate(source_docs)] # 获取完整上下文 full_contexts = [self.doc_id_map.get(did, {"title": "未知", "source": ""}) for did in doc_ids] return { "question": question, "answer": result["result"], "source_documents": source_docs, "full_contexts": full_contexts } def _create_qa_chain(self, retriever) -> Any: """创建问答链""" # 自定义提示模板 prompt_template = """ 基于以下上下文信息,请以专业、准确的方式回答用户的问题。如果上下文信息不足以回答问题,请如实告知用户。 上下文信息: {context} 问题: {question} 请提供详细的回答: """ QA_PROMPT = PromptTemplate( template=prompt_template, input_variables=["context", "question"] ) # 创建问答链 return RetrievalQA.from_chain_type( llm=self.llm, chain_type="stuff", retriever=retriever, return_source_documents=True, chain_type_kwargs={"prompt": QA_PROMPT} ) def add_document(self, content: str, metadata: Dict): """添加单个文档到索引""" if self.vector_db is None: raise ValueError("向量数据库未初始化") # 创建文档对象 doc = Document(page_content=content, metadata=metadata) # 分割文档 split_docs = self._split_documents([doc]) # 添加到索引 self.vector_db.add_documents(split_docs) # 更新文档映射 start_idx = max(self.doc_id_map.keys()) + 1 if self.doc_id_map else 0 for idx, doc in enumerate(split_docs): self.doc_id_map[start_idx + idx] = { "source": doc.metadata["source"], "title": doc.metadata["title"], "category": doc.metadata["category"] } print(f"✅ 添加了 {len(split_docs)} 个文档块") def save_index(self): """保存索引到磁盘""" if self.vector_db is None: raise ValueError("向量数据库未初始化") # 保存索引 self.vector_db.save_local(self.config["index_path"]) # 保存映射表 map_path = os.path.join(os.path.dirname(self.config["index_path"]), "doc_id_map.pkl") with open(map_path, "wb") as f: pickle.dump(self.doc_id_map, f) print(f"✅ 索引已保存至 {self.config['index_path']}") def create_default_config() -> Dict: """创建默认配置 - 使用智谱AI""" return { "data_dir": "data", "index_path": "index/faiss_index", "embedding_model": "sentence-transformers/all-mpnet-base-v2", "embedding_device": "cpu", "llm_provider": "zhipuai", # 默认使用智谱AI "zhipuai_api_key": "1fc6d23e95224503aa94bfcca6a31903.FXoiEbfDgymrE9FA", # 您的智谱AI密钥 "llm_model": "glm-4", # 智谱AI的GLM-4模型 "temperature": 0.7, "chunk_size": 1000, "chunk_overlap": 200, "retrieval_top_k": 5, "score_threshold": 0.4, "auto_download": True } def interactive_cli(): """交互式命令行界面 - 适配智谱AI""" config = create_default_config() # 设置智谱AI API密钥 api_key = input("请输入智谱AI API密钥(或直接回车使用默认值): ") if api_key.strip(): config["zhipuai_api_key"] = api_key # 选择模型 model_choice = input("请选择模型 (1=GLM-4, 2=GLM-3-Turbo, 回车使用GLM-4): ") if model_choice == "2": config["llm_model"] = "glm-3-turbo" # 初始化RAG系统 rag = RAGSystem(config) # 交互问答 print("\nRAG系统已就绪(使用智谱AI),输入问题开始查询(输入'q'退出)") history = [] while True: question = input("\n>>> 问题: ") if question.lower() in ['q', 'quit', 'exit']: break try: result = rag.ask_question(question, history) # 显示结果 print(f"\n💡 答案: {result['answer']}") if result["full_contexts"]: print("\n📚 信息来源:") for i, ctx in enumerate(result["full_contexts"]): print(f" {i + 1}. {ctx['title']} ({ctx['category']})") print(f" 来源: {ctx['source']}") # 添加到历史 history.append({"question": question, "answer": result["answer"]}) except Exception as e: print(f"❌ 错误: {str(e)}") # 保存索引 rag.save_index() print("\n索引已保存,再见!") if __name__ == "__main__": interactive_cli() 】

zip
(1)普通用户端(全平台) 音乐播放核心体验: 个性化首页:基于 “听歌历史 + 收藏偏好” 展示 “推荐歌单(每日 30 首)、新歌速递、相似曲风推荐”,支持按 “场景(通勤 / 学习 / 运动)” 切换推荐维度。 播放页功能:支持 “无损音质切换、倍速播放(0.5x-2.0x)、定时关闭、歌词逐句滚动”,提供 “沉浸式全屏模式”(隐藏冗余控件,突出歌词与专辑封面)。 多端同步:自动同步 “播放进度、收藏列表、歌单” 至所有登录设备(如手机暂停后,电脑端打开可继续播放)。 音乐发现与管理: 智能搜索:支持 “歌曲名 / 歌手 / 歌词片段” 搜索,提供 “模糊匹配(如输入‘晴天’联想‘周杰伦 - 晴天’)、热门搜索词推荐”,结果按 “热度 / 匹配度” 排序。 歌单管理:创建 “公开 / 私有 / 加密” 歌单,支持 “批量添加歌曲、拖拽排序、一键分享到社交平台”,系统自动生成 “歌单封面(基于歌曲风格配色)”。 音乐分类浏览:按 “曲风(流行 / 摇滚 / 古典)、语言(国语 / 英语 / 日语)、年代(80 后经典 / 2023 新歌)” 分层浏览,每个分类页展示 “TOP50 榜单”。 社交互动功能: 动态广场:查看 “关注的用户 / 音乐人发布的动态(如‘分享新歌感受’)、好友正在听的歌曲”,支持 “点赞 / 评论 / 转发”,可直接点击动态中的歌曲播放。 听歌排行:个人页展示 “本周听歌 TOP10、累计听歌时长”,平台定期生成 “全球 / 好友榜”(如 “好友中你本周听歌时长排名第 3”)。 音乐圈:加入 “特定曲风圈子(如‘古典音乐爱好者’)”,参与 “话题讨论(如‘你心中最经典的钢琴曲’)、线上歌单共创”。 (2)音乐人端(创作者中心) 作品管理: 音乐上传:支持 “无损音频(FLAC/WAV)+ 歌词文件(LRC)+ 专辑封面” 上传,填写 “歌曲信息

大家在看

recommend-type

广告识别文本.rar

广告营销类,文本语料,人工收集标注出广告类文本和非广告类文本,可直接跑lgb等二分类模型,对于识别一些广告营销类文本的模型训练,是个不错的语料
recommend-type

专杀工具Zbot或Zeus专杀.zip

专杀工具Zbot或Zeus专杀.zip
recommend-type

docker-gophish:Docker容器的gophish

是一个针对企业和渗透测试人员设计的开源网络钓鱼工具包。 它提供了快速,轻松地设置和执行网络钓鱼攻击以及安全意识培训的能力。 用法 以下是一些示例片段,可帮助您开始创建容器。 码头工人 docker create \ --name=gophish \ -p 443:443 \ -p 3333:3333 \ -v :/data \ --restart unless-stopped \ warhorse/gophish 码头工人组成 与docker-compose v2模式兼容。 --- version: "2" services: gophish: image: warhorse/gophish container_name: gophish environment: ADMIN_USE_TLS: "
recommend-type

intouch 2014R2 SP1版本 永久授权

仅供学习 2014R2SP1 RC 60000 第一大步骤 安装虚拟硬狗,即软狗 1.安装驱动,Virtual USB Multikey64bit driver - Signed a.桌面图标“此电脑 ”右键-属性, 选择"管理",选择“设备管理器” b.“设备管理器”界面,先点击选中计算机名称,点击菜单栏“操作”,选择“添加过时硬件” c.点击“下一步”,选择“安装我手动从列表选择的硬件”并点击“下一步” d.“显示所有设备”,点击“下一步” e.点击“从磁盘安装”,选择“浏览”,找到Virtual USB Multikey64bit driver - Signed文件夹内multikey.inf的文件,并选择 f.一直下一步,中途选择信任,直至安装完成。 如果安装完成后“设备管理器”界面会有一个红色感叹号的设备,自己下载驱动精灵 2.导入虚拟狗,双击 INTOUCH 2014R2SP1 RC 60000\AC5A0000.reg 3.重启电脑 第二大步骤 导入INTOUCH授权, 1. 左下角微软徽标-Invensys-License Manag
recommend-type

提取dxf文件中的图形信息

最新推荐

recommend-type

奥运会科普平台系统-奥运会科普平台系统源码-奥运会科普平台系统代码-springboot奥运会科普平台系统源码-基于springboot的奥运会科普平台系统设计与实现-项目代码

奥运会科普平台系统-奥运会科普平台系统源码-奥运会科普平台系统代码-springboot奥运会科普平台系统源码-基于springboot的奥运会科普平台系统设计与实现-项目代码
recommend-type

Hattrick 是一款简单、快速的跨平台网络安全编码转换工具 Hattrick is a network securi

Hattrick 是一款简单、快速的跨平台网络安全编码转换工具 Hattrick is a network security related code conversion tool..zip
recommend-type

全面收录 Swoole 相关内容的中文 CHM 格式文档

打开下面链接,直接免费下载资源: https://renmaiwang.cn/s/wsszs Swoole 框架的中文版本 CHM 格式文档
recommend-type

自主空中和地对空目标追逐和拦截的导弹制导和弹道控制系统.zip

1.版本:matlab2014a/2019b/2024b 2.附赠案例数据可直接运行。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。
recommend-type

lodger47sina_work_one_25176_1757323922449.zip

lodger47sina_work_one_25176_1757323922449.zip
recommend-type

bls-wasm:Node.js下WebAssembly实现的BLS签名技术

### 知识点说明 #### 标题解析 - **WebAssembly**: 是一种新的代码执行格式,旨在提供一种在现代浏览器和服务器上都能运行的安全、快速的代码执行方式。WebAssembly最初的目标是让网页可以运行高性能的应用程序,比如游戏或视频编辑工具,但随着技术的发展,其应用场景已经扩展到服务器端。Node.js通过引入WebAssembly支持,使得可以在其环境中利用WebAssembly的能力执行高度优化的代码。 - **Node.js**: 是一个基于Chrome V8引擎的JavaScript运行环境,它执行JavaScript代码不需要浏览器支持。Node.js被设计为能够构建快速、可扩展的网络应用程序,尤其擅长处理大量并发连接的场景。 - **BLS签名**:BLS(Boneh-Lynn-Shacham)签名是一种基于密码学的签名方案。它在安全性、效率和功能上优于传统的ECDSA和RSA签名算法。BLS签名特别适合于区块链等需要快速验证大量签名的场景。 #### 描述解析 - **密钥和签名模型**: 描述了BLS签名方案中的基本要素:`Fr:SecretKey` 表示秘密密钥,而 `G2:PublicKey` 表示公钥。G1用于表示签名。在密码学中,密钥和签名的生成、使用和管理是确保系统安全的基础。 - **以太坊2.0兼容性**: 提到如果需要与以太坊2.0兼容的签名/验证,需要参考某些文档或指南。这暗示了`bls-wasm`库在区块链领域的重要性,特别是针对以太坊这样的平台,其正在向2.0版本升级,而新的版本将会使用BLS签名来改进网络的安全性和性能。 #### 使用指南 - **Node.js使用**: 通过`require('bls-wasm')`语句引入模块,展示了如何在Node.js环境中集成`bls-wasm`模块。 - **浏览器使用**: 对于在浏览器中使用,需要引入`bls.js`,并且通过`require('bls-wasm/browser')`的方式引入。这反映了WebAssembly模块的跨平台特点,能够适应不同的运行环境。 - **React使用**: 通过类似的方式`const bls = require('bls-wasm/browser')`说明了在React项目中如何集成`bls-wasm`。 - **版本兼容性**: 提到v0.4.2版本破坏了入口点的向后兼容性,意味着从这个版本开始,库的API可能发生了变更,需要开发者注意更新。 #### 执照信息 - **修改了新的执照**: 说明了关于软件许可证的新变化,暗示了库的许可证可能由之前的版本有所更新,需要用户关注和遵守新的许可证条款。 #### 压缩包文件信息 - **bls-wasm-master**: 由于提供了压缩包文件的名称列表,暗示了一个名为`bls-wasm`的项目,可能包含源代码、编译后的文件、文档等。 ### 知识点的深入拓展 #### WebAssembly在Node.js中的应用 WebAssembly在Node.js中的主要优势在于性能的提升,特别是在处理CPU密集型任务时。WebAssembly模块可以运行C/C++、Rust等语言编写的代码,并且这些代码在WebAssembly的沙盒环境中执行得非常快。 #### BLS签名在区块链中的作用 区块链技术依赖于密码学来确保交易的安全性和验证性。BLS签名因其在密钥长度、签名长度、签名速度以及多签性能等方面的优点,非常适合被用于区块链网络。它允许验证者更快地验证交易,并提高了区块链的处理能力。 #### Node.js环境下的安全实践 在Node.js环境中使用BLS签名或任何加密算法时,应当遵循安全实践,例如确保密钥的安全管理,避免在不安全的通道中传输密钥,以及定期更新和轮换密钥等。 #### 跨平台兼容性的重要性 对于WebAssembly模块来说,能够在不同的环境(如Node.js、浏览器、React应用等)中无缝工作是至关重要的。开发者需要关注不同平台间的API差异和兼容性问题。 #### 软件许可证的遵守 软件许可证规定了开发者如何使用该软件,以及他们可以对软件进行哪些修改和分发。遵循许可证的规定不仅可以避免法律风险,还可以确保代码的使用和传播不会侵犯原作者的权益。 综上所述,`bls-wasm`模块作为一个在WebAssembly环境下运行的BLS签名工具,为Node.js和Web开发者提供了强大的密码学能力,特别是对于希望支持以太坊2.0等区块链技术的项目。开发者在使用这类工具时,需要关注性能、兼容性、安全性和许可证等多方面的要求。
recommend-type

提升Linux终端使用效率的实用指南

### 提升 Linux 终端使用效率的实用指南 #### 1. i3wm 窗口管理基础操作 在 i3wm 中,创建新的窗口块(tiles)就等同于打开应用程序,因为所有应用程序都以窗口块的形式呈现在窗口管理器的网格中。 - **创建窗口块**: - 打开终端:使用 `win + enter`。 - 打开其他应用程序:按下 `win + d`,屏幕左上角会弹出一个小对话框,输入应用程序名称,对话框会显示自动补全状态,当显示目标程序时,按下“打开”,应用程序将以窗口块形式打开。 - **窗口块布局调整**: - 打开更多应用程序会在工作区自动创建更多窗口块,并在网格中分
recommend-type

现有以下数据: String[] keyAry: [{"fields":[{"name":"类型"}, {"name":"中问题", "width":"400px"}, {"name":"小问题", "width":"400px"}]}] String[] value: [{"fieldvalues":[{"value":"人员","row":0,"col":0},{"value":"1","row":0,"col":1},{"value":"1","row":0,"col":2}]},{"fieldvalues":[{"value":"设施","row":1,"col":0},{"value":"2","row":1,"col":1},{"value":"2","row":1,"col":2}]}] 请使用java语言将以上数据转化为word的表格,具体格式如下: 类型 中问题 小问题 人员 1 1 设施 2 2 其中,表格第一行是keyAry数组的name属性,value数组中每个fieldvalues属性作为一行

<think> 我们使用Apache POI库来操作Word文档生成表格。 步骤: 1. 创建文档对象,并创建一个表格。 2. 首先,我们创建表头行(第一行),遍历keyAry数组,取出每个元素的name属性作为表头单元格的内容。 3. 然后,遍历value数组,每个元素代表一行数据。每个元素有一个fieldvalues数组,这个数组中的每个元素对应一个单元格。 4. 注意:keyAry数组的长度应该与fieldvalues数组的长度一致,因为它们分别代表列名和每列的值。 假设数据结构如下: keyAry: 数组,每个元素是一个对象,对象有name属性(表头名称) v
recommend-type

2000年代初的粉丝创神奇宝贝网站回顾

标题和描述中提到的“jps1:杰西(Jesse)基于粉丝的终极口袋妖怪网站(2000-2001)”反映了以下几个重要知识点: 1. 网站建设与维护的早期阶段:从2000到2001年的时间段中,互联网技术正处于快速发展时期,而杰西(Jesse)创建的这个口袋妖怪主题网站,可以被视作个人站长时代的早期代表作。这代表了早期网络用户利用有限资源进行个人兴趣爱好的分享和推广。 2. 基于粉丝的互动平台:这个网站明确指出是基于粉丝而创建的,这表明了网络社区中粉丝文化的存在和影响力。在那个时期,围绕特定兴趣(如口袋妖怪)形成的粉丝群体,通过这些网站交流信息、分享资源,这种基于共同兴趣建立的社区模式对后来的社交媒体和粉丝经济有着深远影响。 3. 个人网站的存档意义:杰西(Jesse)在描述中提到了出于存档目的而发布,这说明了这个网站对于网络历史保存的重要性。随着互联网内容的快速更迭,个人网站往往由于服务器迁移、技术更新等原因而丢失,因此存档个人网站是对互联网文化遗产的一种保护。 关于标签“JavaScript”,它指向了一个重要的知识点: 4. JavaScript在网络技术中的作用:标签“JavaScript”点出了该网站使用了JavaScript技术。作为早期的动态网页脚本语言,JavaScript在提高用户交互体验、网页特效实现等方面发挥了关键作用。尽管该网站发布的年份较早,但极有可能包含了一些基础的JavaScript代码,用于实现动态效果和基本的客户端交互。 至于“压缩包子文件的文件名称列表”中的“jps1-gh-pages”,它暗示了以下知识点: 5. GitHub Pages的使用:GitHub Pages是GitHub提供的一项服务,允许用户将网站内容部署到一个独立的域名下,通过“jps1-gh-pages”文件名我们可以推测,这个口袋妖怪网站可能是被部署在GitHub Pages上的。这表明了即使在早期,个人站长已经开始利用现代网络服务来托管和分享他们的项目。 6. 压缩文件的作用:文件名称中的“压缩”二字意味着该网站的文件内容可能是经过压缩处理的,这可能是为了便于存储和传输。在互联网早期,由于带宽和存储空间的限制,压缩文件是一种常见的数据管理手段。 总结以上知识点,可以归纳为: - 网站建设与维护的早期案例,以及个人站长时代的特点。 - 基于粉丝文化的网络社区,及其对后来社交媒体的影响。 - 个人网站的存档价值和对互联网文化遗产的贡献。 - JavaScript的早期应用以及它在改善用户交互体验方面的重要性。 - GitHub Pages的使用案例,以及压缩技术在网络数据管理中的应用。 从这些知识点可以看出,即便是早期的个人网站项目,也蕴含了丰富的技术和文化内涵,为理解互联网的发展和应用提供了重要的视角。
recommend-type

Linux终端实用工具与技巧

# Linux 终端实用工具与技巧 ## 1. gnuplot 绘图与导出 ### 1.1 绘制方程图形 任何方程都可以用特定方式绘制图形。例如,一个斜率为 5、y 轴截距为 3 的直线方程,可使用以下命令生成图形: ```bash plot 5*x + 3 ``` ### 1.2 导出图形为图像文件 虽然能在终端显示图表,但多数情况下,我们希望将图表导出为图像,用于报告或演示。可按以下步骤将 gnuplot 设置为导出图像文件: 1. 切换到 png 模式: ```bash set terminal png ``` 2. 指定图像文件的输出位置,否则屏幕将显示未处理的原始 png 数据: