做企业网站设计价格是多少钱建设网站的功能地位
2026/4/2 16:24:28 网站建设 项目流程
做企业网站设计价格是多少钱,建设网站的功能地位,如何软件网站优化公司,山西网站建设排名RAG#xff08;检索增强生成#xff09;本质上就是给AI模型外挂一个知识库。平常用ChatGPT只能基于训练数据回答问题#xff0c;但RAG可以让它查阅你的专有文档——不管是内部报告、技术文档还是业务资料#xff0c;都能成为AI的参考资源。 很多人第一反应是用LangChain或L…RAG检索增强生成本质上就是给AI模型外挂一个知识库。平常用ChatGPT只能基于训练数据回答问题但RAG可以让它查阅你的专有文档——不管是内部报告、技术文档还是业务资料都能成为AI的参考资源。很多人第一反应是用LangChain或LlamaIndex这些现成框架确实能快速搭起来。但自己实现的核心价值在于你能清楚知道文档是怎么被切分的、向量是怎么生成的、检索逻辑具体怎么跑的。当系统出现检索不准确、回答质量差、成本过高这些问题时你能精确定位到是哪个环节的问题。比如是分块策略不合适还是embedding模型选择有问题或者是检索参数需要调整。用框架的话很多时候只能盲目调参数治标不治本。另外业务场景往往有特殊需求PDF表格要特殊处理、某些文档类型需要提取特定元数据、检索结果要按业务规则重排序等等。自己实现就能在任何环节做针对性优化而不是被框架的设计限制住。下面我们开始一步一步的进行文档解析让机器能读懂你的文件做RAG第一步是把各种格式的文档统一处理成纯文本。PDF、Word、txt这些常见格式各有各的解析方式。import os import PyPDF2 import docx def load_plain_text(file_path: str) - str: Load and return the full contents of a .txt file. with open(file_path, r, encodingutf-8) as fp: return fp.read() def extract_text_from_pdf(file_path: str) - str: Read every page of a PDF and stitch the text together. texts [] with open(file_path, rb) as fp: reader PyPDF2.PdfReader(fp) for pg in reader.pages: # ensure we dont end up with None page_txt pg.extract_text() or texts.append(page_txt) # separate pages with a newline return \n.join(texts) def extract_text_from_docx(file_path: str) - str: Grab all paragraphs from a .docx document. doc docx.Document(file_path) paras [p.text for p in doc.paragraphs] return \n.join(paras)然后写个统一的路由器根据文件后缀调用对应的解析函数import os def load_document(file_path: str): Load a documents text based on its file extension. _, extension os.path.splitext(file_path) extension extension.lower() if extension .txt: return read_text_file(file_path) elif extension .pdf: return read_pdf_file(file_path) elif extension .docx: return read_docx_file(file_path) else: raise ValueError(fUnsupported file type: {extension})这样设计的好处是文档结构保持完整用换行符分隔段落支持各种大小写的文件扩展名不支持的格式会给出明确提示。文本分块把长文档切成合适的片段因为有上下文的的限制所以直接把整篇文档丢给LLM就像让人一口吃下整个pizza——不现实。所以需要把文档切成适当大小的块。def chunk_sentences(text: str, max_length: int 500) - list[str]: Split text into size-limited chunks, breaking only at sentence boundaries. # Normalize whitespace and split on basic sentence delimiter segments text.replace(\n, ).split(. ) blocks [] buffer [] buffer_len 0 for segment in segments: seg segment.strip() if not seg: continue # skip empty strings # Make sure each segment ends with a period if not seg.endswith(.): seg . seg_len len(seg) # If adding this segment would exceed max_length, flush the buffer first if buffer and buffer_len seg_len max_length: blocks.append( .join(buffer)) buffer [seg] buffer_len seg_len else: buffer.append(seg) buffer_len seg_len # Append any remaining sentences if buffer: blocks.append( .join(buffer)) return blocks块大小选择是个权衡问题。小块200-500字符适合精确匹配像索引卡一样中等块500-1000字符能保留更多上下文大块1000字符上下文丰富但可能模糊焦点。技术文档通常用小块效果更好叙述性内容可以用大一些的块并且分块还可以有很多策略可选在以前的文章中都有总结。搭建向量数据库用ChromaDB存储语义信息文档切块后需要存到向量数据库里这样才能做语义搜索。ChromaDB是个不错的选择轻量但功能够用。import chromadb from chromadb.utils import embedding_functions # Persistent storage - saves data between sessions client chromadb.PersistentClient(pathchroma_db) # Our brain for understanding text meaning sentence_transformer_ef embedding_functions.SentenceTransformerEmbeddingFunction( model_nameall-MiniLM-L6-v2 # Compact but powerful ) # Create our knowledge repository collection client.get_or_create_collection( namedocuments_collection, embedding_functionsentence_transformer_ef )这里用了几个核心组件PersistentClient确保数据持久化存储重启程序后数据还在SentenceTransformerEmbeddingFunction把文本转成向量让机器理解语义all-MiniLM-L6-v2是个轻量级但效果不错的embedding模型。文档索引批量处理和元数据管理接下来要把文档批量处理成可检索的格式。每个文本块都需要唯一ID和元数据方便后续溯源。def build_knowledge_units(path: str): Ingest a file, break it into chunks, and tag each piece with metadata. try: # Pull in the raw text raw load_document(path) # Break the text into bite-sized segments segments partition_text(raw) # Grab just the filename for provenance name os.path.basename(path) # Assemble metadata dicts for each segment metadata_records [ {source_file: name, segment_index: idx} for idx in range(len(segments)) ] # Generate a stable ID for each piece unique_keys [ f{name}_seg_{idx} for idx in range(len(segments)) ] return unique_keys, segments, metadata_records except Exception as err: print(fFailed to process {path}: {err}) # Return empty lists so downstream code can continue safely return [], [], []为了提高效率批量插入比单条插入快很多def batch_insert_into_store(store, record_ids, contents, metadata_list): Insert items into the vector store in optimized batches. batch_size 100 # tuned for ChromaDB throughput for start_idx in range(0, len(contents), batch_size): stop_idx min(start_idx batch_size, len(contents)) store.add( documentscontents[start_idx:stop_idx], # text chunks metadatasmetadata_list[start_idx:stop_idx],# chunk metadata idsrecord_ids[start_idx:stop_idx] # unique chunk IDs ) def ingest_folder(store, directory: str): Walk a directory, process each file, and load into the store. # gather only regular files entries [ os.path.join(directory, name) for name in os.listdir(directory) if os.path.isfile(os.path.join(directory, name)) ] for path in entries: filename os.path.basename(path) print(f► Processing {filename} …) ids, contents, metadata_list process_document(path) if contents: batch_insert_into_store(store, ids, contents, metadata_list) print(f✔ Loaded {len(contents)} chunks from {filename})实际运行时你会看到这样的输出► Processing customer_faqs.pdf … ✔ Loaded 51 chunks from customer_faqs.pdf ► Processing onboarding_guide.docx … ✔ Loaded 20 chunks from onboarding_guide.docx语义检索找到最相关的内容块有了向量数据库就能进行语义搜索了。不是简单的关键词匹配而是理解查询的语义含义。def run_semantic_query(collection, query: str, top_k: int 2): Run a semantic search to find the most relevant chunks. return collection.query( query_texts[query], # The actual search query n_resultstop_k # Number of matches to return ) def build_context_and_citations(results): Combine matched chunks and reference their original sources. combined_text \n\n.join(results[documents][0]) references [ f{meta[source]} (chunk {meta[chunk]}) for meta in results[metadatas][0] ] return combined_text, references想了解底层发生了什么可以看看搜索结果的详细信息def display_search_hits(results): Nicely formatted display of search output for readability. print(\nTop Matches\n * 50) hits results[documents][0] metadata results[metadatas][0] scores results[distances][0] for idx in range(len(hits)): snippet hits[idx] info metadata[idx] score scores[idx] print(f\nMatch #{idx 1}) print(fFrom: {info[source]} — Chunk {info[chunk]}) print(fSimilarity Score: {1 - score:.2f} / 1.00) print(fExcerpt: {snippet[:150]}...\n)搜索结果会显示相似度分数和来源文档帮你判断检索质量。接入LLM让模型基于检索内容回答检索到相关内容后就要让LLM基于这些内容生成回答。关键是构造好的prompt确保模型只基于提供的上下文回答。import os from openai import OpenAI # Initialize the OpenAI client client OpenAI() # Set your OpenAI API key os.environ[OPENAI_API_KEY] your_api_key # Replace this with your actual key def build_prompt(context: str, question: str) - str: Construct a focused prompt using context and a user question. return fYou are a helpful assistant. Use only the context provided below to answer. If the answer cannot be found in the context, reply with I dont have that information. Context: {context} Question: {question} Answer: def ask_openai(question: str, context: str) - str: Send the prompt to OpenAI and return the generated response. prompt build_prompt(context, question) try: reply client.chat.completions.create( modelgpt-4-turbo, messages[ {role: system, content: You answer based strictly on the context provided.}, {role: user, content: prompt} ], temperature0.3, max_tokens300 ) return reply.choices[0].message.content except Exception as err: return fError: {str(err)}temperature参数控制生成的随机性0.0最保守只输出事实0.5平衡事实和表达1.0最有创造性。对RAG来说0.0到0.3比较合适保证回答基于文档内容。对话记忆让AI记住聊天历史ChatGPT能记住对话上下文我们的RAG系统也需要这个能力。实现起来其实不复杂就是维护一个会话状态。import uuid from datetime import datetime # In-memory chat log (swap with persistent storage in production) chat_sessions {} def start_new_session() - str: Initialize a fresh conversation session with a unique ID. session_id str(uuid.uuid4()) chat_sessions[session_id] [] return session_id def log_message(session_id: str, sender: str, message: str): Add a message to the session history. if session_id not in chat_sessions: chat_sessions[session_id] [] chat_sessions[session_id].append({ role: sender, content: message, timestamp: datetime.now().isoformat() }) def fetch_recent_messages(session_id: str, limit: int 5): Return the last few messages from a session. msgs chat_sessions.get(session_id, []) return msgs[-limit:] def prepare_history_for_model(messages: list) - str: Convert messages into a single formatted string. return \n.join( f{msg[role].capitalize()}: {msg[content]} for msg in messages )这样设计后每个用户的对话都有独立的session_id每条消息都会记录到历史中生成回答时可以参考最近的几条消息作为上下文。解决指代消解理解它、那个指的是什么用户经常会问一些不完整的问题比如先问LaunchPad项目是什么接着问它什么时候开始的。这里的它显然指LaunchPad但AI不知道。需要把后续问题重写成独立完整的问题。def rewrite_query_with_context(query: str, chat_log: str, client: OpenAI) - str: Rewrites a follow-up query as a full standalone question using prior conversation. prompt fRephrase follow-up questions to be fully self-contained. Refer to the chat history as needed. Return only the rewritten question. Chat History: {chat_log} Follow-up: {query} Standalone Question: try: response client.chat.completions.create( modelgpt-3.5-turbo, # Fast, cheap, reliable messages[{role: user, content: prompt}], temperature0 # Keep output consistent ) return response.choices[0].message.content except Exception as err: print(fFailed to contextualize query: {err}) return query # Return original if theres an error这样它什么时候开始的就能自动变成LaunchPad项目什么时候开始的确保搜索能找到正确的内容。完整的对话流程把所有组件串起来最后把所有功能整合成一个完整的对话式RAG系统def handle_conversational_query( collection, query: str, session_id: str, n_chunks: int 3 ): Orchestrates the full RAG-based QA flow in a chat session. # Step 1: Pull session history and prep it for context injection chat_log get_conversation_history(session_id) prior_messages format_history(chat_log) # Step 2: Resolve pronouns or unclear references in the query refined_query contextualize_query(query, prior_messages, client) print(f[Refined Query] {refined_query}) # Step 3: Retrieve relevant knowledge from the vector DB search_results run_semantic_query(collection, refined_query, n_chunks) retrieved_text, citations build_context_and_citations(search_results) # Step 4: Generate an answer grounded in retrieved content answer generate_response(refined_query, retrieved_text) # Step 5: Save both user input and AI reply into memory add_message(session_id, user, query) add_message(session_id, assistant, answer) return answer, citations实际使用时的对话流程session start_conversation() # 初始查询 q1 LaunchPad是做什么的 reply, refs smart_retrieval(collection, q1, session) print(fAnswer: {reply}\nSources: {refs}) # 后续查询 q2 它什么时候开始的 reply, refs smart_retrieval(collection, q2, session) print(fAnswer: {reply}\nSources: {refs})系统会自动处理指代消解输出类似这样ContextualizedLaunchPad是做什么的 AnswerLaunchPad帮助初创公司快速原型设计和验证产品想法。 Sources[program_overview.pdf (chunk 1)] ContextualizedLaunchPad项目什么时候开始的 AnswerLaunchPad项目始于2018年。 Sources[timeline_notes.txt (chunk 3)]几个实用的优化技巧做完基础功能后还有一些进阶优化可以考虑。1、混合搜索能结合语义搜索和元数据过滤# 在语义搜索中添加元数据过滤 collection.query( query_texts[query], n_results5, where{department: HR} # 只搜索HR部门的文档 )2、自动添加来源引用让用户知道答案的出处# 在回答后自动添加来源链接 def enhance_response(response, sources): return f{response}\n\n来源:\n \n.join( f- {source} for source in sources )3、根据文档类型调整分块策略# 根据文档类型动态调整块大小 if financial in file_name: chunks split_text(content, chunk_size300) # 财务文档用小块 else: chunks split_text(content, chunk_size600) # 其他文档用大块4、长对话需要压缩历史# 当对话历史太长时自动摘要 def summarize_history(history): prompt f总结以下对话的关键信息:\n{history} return client.chat.completions.create(/*...*/).choices[0].message.content总结–从零实现RAG系统确实比用现成框架麻烦一些但带来的好处很明显。你对每个环节都有完全控制权可以根据具体需求精确调优。出了问题能快速定位不用在框架的抽象层里瞎猜。成本也更透明每个API调用、每个token都在你掌控之中。更重要的是你真正理解了RAG的工作原理而不是只会调用几个封装好的函数。这种理解在遇到复杂场景时价值巨大。虽然初期投入的时间多一些但长期来看绝对值得。特别是对于有特定需求的业务场景自实现的灵活性是框架无法比拟的。普通人如何抓住AI大模型的风口领取方式在文末为什么要学习大模型目前AI大模型的技术岗位与能力培养随着人工智能技术的迅速发展和应用 大模型作为其中的重要组成部分 正逐渐成为推动人工智能发展的重要引擎 。大模型以其强大的数据处理和模式识别能力 广泛应用于自然语言处理 、计算机视觉 、 智能推荐等领域 为各行各业带来了革命性的改变和机遇 。目前开源人工智能大模型已应用于医疗、政务、法律、汽车、娱乐、金融、互联网、教育、制造业、企业服务等多个场景其中应用于金融、企业服务、制造业和法律领域的大模型在本次调研中占比超过30%。随着AI大模型技术的迅速发展相关岗位的需求也日益增加。大模型产业链催生了一批高薪新职业人工智能大潮已来不加入就可能被淘汰。如果你是技术人尤其是互联网从业者现在就开始学习AI大模型技术真的是给你的人生一个重要建议最后只要你真心想学习AI大模型技术这份精心整理的学习资料我愿意无偿分享给你但是想学技术去乱搞的人别来找我在当前这个人工智能高速发展的时代AI大模型正在深刻改变各行各业。我国对高水平AI人才的需求也日益增长真正懂技术、能落地的人才依旧紧缺。我也希望通过这份资料能够帮助更多有志于AI领域的朋友入门并深入学习。真诚无偿分享vx扫描下方二维码即可加上后会一个个给大家发大模型全套学习资料展示自我们与MoPaaS魔泊云合作以来我们不断打磨课程体系与技术内容在细节上精益求精同时在技术层面也新增了许多前沿且实用的内容力求为大家带来更系统、更实战、更落地的大模型学习体验。希望这份系统、实用的大模型学习路径能够帮助你从零入门进阶到实战真正掌握AI时代的核心技能01教学内容从零到精通完整闭环【基础理论 →RAG开发 → Agent设计 → 模型微调与私有化部署调→热门技术】5大模块内容比传统教材更贴近企业实战大量真实项目案例带你亲自上手搞数据清洗、模型调优这些硬核操作把课本知识变成真本事‌02适学人群应届毕业生‌无工作经验但想要系统学习AI大模型技术期待通过实战项目掌握核心技术。零基础转型‌非技术背景但关注AI应用场景计划通过低代码工具实现“AI行业”跨界‌。业务赋能突破瓶颈传统开发者Java/前端等学习Transformer架构与LangChain框架向AI全栈工程师转型‌。vx扫描下方二维码即可本教程比较珍贵仅限大家自行学习不要传播更严禁商用03入门到进阶学习路线图大模型学习路线图整体分为5个大的阶段04视频和书籍PDF合集从0到掌握主流大模型技术视频教程涵盖模型训练、微调、RAG、LangChain、Agent开发等实战方向新手必备的大模型学习PDF书单来了全是硬核知识帮你少走弯路不吹牛真有用05行业报告白皮书合集收集70报告与白皮书了解行业最新动态0690份面试题/经验AI大模型岗位面试经验总结谁学技术不是为了赚$呢找个好的岗位很重要07 deepseek部署包技巧大全由于篇幅有限只展示部分资料并且还在持续更新中…真诚无偿分享vx扫描下方二维码即可加上后会一个个给大家发

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询