首页 文章 精选 留言 我的

精选列表

搜索[自我进化],共7191篇文章
优秀的个人博客,低调大师

LlamaFactory × 多模态RAG × Chat-BI,万字长文揭秘RAG进化迷踪,打造专业AI助手!

你有没有想过,大模型如何更聪明地回答问题?🤔当传统 RAG 遇上多模态与商业智能(BI),会碰撞出怎样的火花?🤔 今天我们将围绕医学这个专业领域,一步步搭建出一个集众多本领于一身的小型智能AI医学问答系统,全程干货预警,记得备好笔记本! 下图和视频效果是我们今天的目标!涉及多路召回多模态RAG、多模态问答、Chat-BI、Agent、LLM微调、多模态模型微调等等。让我们开始吧! 😽 小声说一句 文末有免费大礼包 一、朴素 RAG:大模型的「初代智能助手」 什么是 RAG?让 AI 边查资料边回答! RAG(检索增强生成,Retrieval-Augmented Generation)是一种结合信息检索(Retrieval)和文本生成(Generation)的技术,用于提高大模型的准确性和实用性。通过在生成文本前检索外部知识库中的相关信息,RAG 可以让大模型在回答问题时结合最新、最相关的数据,从而减少幻觉现象,并提升答案的专业性和时效性。 简单说就是:让大模型在回答问题前,先去「翻书」(检索知识库),再结合最新资料输出答案! ✨核心优势: 告别「幻觉」:用真实数据撑腰,拒绝瞎编 与时俱进:实时抓取最新信息,知识不过期 专业度 UP:领域知识库加持,回答更靠谱 Naive RAG:AI 的「基础解题套路」 先来看最基础的 RAG 工作流,像不像学生写作业? 💡 步骤分解: 审题(用户提问):比如「推荐适合上班族的护眼食物」 查资料(检索模块):从食谱数据库中找出含维生素 A、叶黄素的食材列表 写答案(生成模块):结合检索到的食材,推荐食谱并解释原理 🔍关键技术点: ① 检索(Retrieval) 用户输入问题后,系统会基于该输入在外部知识库或向量数据库中检索相关内容。通常使用语义搜索(Semantic Search)或 BM25、Dense Retrieval(DPR)、Embedding-based Retrieval 等技术来匹配最相关的文档片段。 ② 增强(Augmented) 检索到的文本内容会作为额外的上下文,与用户输入一起提供给 大模型。这一阶段涉及 Prompt 设计,确保大模型在生成回答时充分利用检索到的信息,而非仅依赖其内部知识。 ③ 生成(Generatation) 大模型结合检索到的信息和自身的预训练知识,生成最终的回答。这一过程可能涉及对检索信息的重构、摘要或融合,以确保答案的连贯性、准确性和可读性。 🌟 优点: 简单高效:由于模块化设计,容易实现和调试。✅ 可扩展性强:检索模块和生成模块可以独立优化或替换。✅ ⚠️ 局限性: 单模态依赖:仅依赖文本作为输入和检索内容,无法有效处理多模态数据。❌ 领域水土不服:通常直接使用通用领域LLM,未针对领域知识或任务需求进行微调。❌ 二、多模态能力接入:让模型秒变「图文全能王」 多模态 RAG:让模型拥有「超级感官」 传统 RAG 只能 “读文字”,多模态 RAG 却能 “看图片、听声音”!通过多模态嵌入技术,把文字、图像、音频全塞进同一个 “语义魔法空间”,让模型既能精准检索图文中的隐藏信息,又能生成会 “动起来” 的回答。在医学领域,多模态RAG的跨模态检索与生成能力正在展现出颠覆性价值,例如在肺部疾病诊断中,系统可以同时针对患者的CT影像切片、病理报告文本对患者做出诊断。下面我们将从整体架构出发,带领读者深入了解多模态 RAG 的基本原理及其作用。 多模态 RAG VS 基础 RAG:升级点大揭秘! 基础的RAG主要针对文本数据进行了检索与生成。然而,要支持多模态输入和输出,需要对基础 RAG 架构进行一定的调整和扩展。 首先,需要修改的模块包括: 检索模块:从仅支持文本检索,到需要扩展为支持多模态检索,例如图像、音频等信息的索引和匹配。 生成模块:基础 RAG 仅针对文本生成,现在需要扩展支持多模态输出,如文本结合图像、音频的生成能力。 其次,需要新增的模块包括以下四个部分: 模块 功能 多模态编码器🛠️ 用于对不同模态的数据(文本、图像、音频等)进行编码,以便统一表示并用于检索和生成。 多模态融合器🧪 用于融合不同模态的信息,使其能够协同作用,提高生成内容的准确性和丰富度。 跨模态检索器🔍 支持输入多种数据格式,并能在多模态知识库中找到相关信息。 多模态解码器🎬 负责将生成结果解码为多种形式,如文本、图片、语音等,以适应不同的输出需求。 多模态RAG的核心组件 为了支持多模态输入和输出,调整和扩展后的多模态RAG 流程图如下。 下面简单讲一下每个组件的功能以及相关输入输出示例。 ✨ 多模态编码与融合:打破信息次元壁 在多模态RAG系统中,多模态编码模块是将不同类型的输入(如文本、图像、音频等)统一映射到向量空间的关键组件。其主要作用是对用户查询和知识库内容进行编码,以便进行相似度检索与上下文构建。 相比于传统仅处理文本的 RAG,多模态 RAG 需要将图文等多源信息编码进行统一编码,从而实现跨模态信息的理解与匹配。 📖 文本编码常用模型: BAAI/bge系列(如 bge-m3:支持多语言和长文本处理,生成高质量语义嵌入) Cohere Embed(提供高效的语义编码和上下文理解,适用于文本检索与生成任务) GTE-large(专注于高精度语义匹配与检索,适合大规模文本数据处理) 🎨 多模态编码常用模型: 图像编码:NFNet-F6、ViT、CLIP ViT 音频编码:Whisper、CLAP 视频编码:CMVC 在RAG系统中,多模态数据编码的融合是一个核心问题。为实现跨模态信息的有效交互与检索,我们需要将不同模态的数据映射到一个统一的向量空间中。这样,不论是文字还是非文字信息,都可以在同一语义空间中进行相似性度量、检索和生成任务。这里介绍三种常用方法。 统一模态:将非文本模态(如图像、音频、表格)转换为描述性文本,再用文本编码器统一编码,得到语义向量。 共享向量空间:通过多模态编码器(如CLIP、CLAP)直接将多模态数据编码到同一向量空间,无需中间转换,保留原始信息,统一接口,工程友好。 分离检索:不同模态使用专门模型分别编码,检索阶段融合结果,灵活性强,适配性好,适合复杂场景。 🔍 多模态检索模块:想查什么就查什么 1.基础检索 处理单一模态的查询,如文本到文本、图像到图像的匹配。例如当输入为文本查询,如"患者出现持续性干咳、低热,胸部CT显示双肺磨玻璃影"时,则会输出相关文本段落,如 "持续性干咳、低热伴双肺磨玻璃影常见于病毒性肺炎、间质性肺病或早期肺结核";而当输入为图像查询时,如一张胸部CT图像时,则会输出胸部CT的相关图像。 2.跨模态检索 支持跨模态查询,例如文本查询匹配图像,或图像查询匹配文本。例如当输入为文本时,如"一张胸部正位CT图像",则会输出最相关的胸部CT的图片;而当输入为胸部CT的照片时,则会输出相关描述文本,如 "这是一张胸部正位CT图像,存在左侧气胸"。 🎨 多模态生成模块:会输出图片的 AI 写手 原有 RAG 仅支持文本生成,现在扩展为支持多模态输出,例如生成带有图片的回答或结合语音的解释。当输入为文本查询时,如"查询数据库中所有论文的题目,基于题目内容将论文聚类为5类,用柱状图展示每类的论文数量,此外每类分别列举几个文章。" ,则会将相关检索结果(文本、图片)传给大模型,最后输出图文回答,如相关文本 + 一张论文类别数量的柱状图。 三、多模态 + BI:复杂 RAG 架构实战 通过前面的探索,我们已经了解了朴素 RAG 如何让大模型具备「查资料再回答」的基础能力,也见证了多模态 RAG 通过图文融合实现的「感官升级」。但当实际应用场景涉及「医院年度病例统计分析」「科研文献数据可视化呈现」等需求时,单纯的多模态处理仍显不足 —— 这类场景既需要解析医学影像、病历文本等非结构化数据,又要对接数据库完成指标计算、图表生成等 BI任务。 如何让 RAG 系统同时驾驭多模态理解与结构化数据分析?接下来要展开的「多模态 + BI」复杂架构实战,正是为解决这类「既要又要」的高阶需求而生,我们将在朴素 RAG 基础上层层叠加关键模块,最终打造出能同时处理影像诊断、数据统计、图表生成的「全能型 AI 助手」! 首先登场的是 —— VQA 模块(Visual Question Answering) 当用户提问中包含图片时,系统会自动触发 VQA,对图像进行结构化信息提取,挖掘上下文关键内容;若没有图像,就跳过这步,直接进入文本处理环节,效率UPUP❗❗ 接下来,系统通过意图识别模块,将不同类型的问题智能分流: 🔹 论文问答? 走传统 RAG 路线!向量检索+大模型生成,精准提取相关文献内容。 🔹 统计问答? 开启 SQL 模式!从提问中抽取结构化信息(如指标、维度、过滤条件),自动生成 SQL 查询,查询结果再由大模型「翻译」成自然语言,一目了然。 ✅ 与传统 RAG 的核心差异 维度 传统 RAG 系统 多模态 + BI 的 RAG 系统 输入类型 仅文本 query 文本 + 可选图像 感知能力 无图像理解 引入 VQA,具备视觉问答能力 意图处理 默认文本问答 多路径意图识别(论文问答 vs 统计问答) 检索类型 向量检索文本块 文本向量检索 + 图像信息提取 + 表格 SQL 检索 响应方式 直接生成答案 根据意图生成带统计分析的答案或论文图文回答 应用场景 普通问答、文档 QA 支持论文 QA + 数据分析(BI)混合场景 数据准备 以 ArXivQA 数据集为例,从 Papers-2024.md 中的100篇论文构建知识库和数据库,在准备数据之前需要先下载论文信息文件(内含论文链接),可以离线下载或者以下命令进行下载: wget https://raw.githubusercontent.com/taesiri/ArXivQA/main/Papers-2024.md -O 2024.md 我们需要从两方面去准备数据(以医学领域为例): 📚 医学知识库:存储论文全文到指定目录,用于文献类问答 📊 医学数据库:提取论文元信息(如标题、作者等)到本地数据库,用于统计类问答,论文信息如title、author等 以下脚本可以一步搭建医学论文信息的数据库👇 import re import os import requests import time import json from tqdm import tqdm from bs4 import BeautifulSoup import sqlite3 # 医学相关关键词列表 keywords = ['brain', 'disease', 'cancer', 'tumor', 'medical', 'health', 'clinical', 'biomedical', 'neuro', 'diagnosis', 'imaging'] def contains_keyword(text, keywords): text = text.lower() for kw in keywords: if kw.lower() in text: return True return False def download_pdf(pdf_url, title): try: safe_title = re.sub(r'[\\/*?:"<>|]', "", title)[:200] os.makedirs('kbs', exist_ok=True) filename = f"kbs/{safe_title}.pdf" if os.path.exists(filename): return filename response = requests.get(pdf_url, stream=True, timeout=50) response.raise_for_status() with open(filename, 'wb') as f: for chunk in response.iter_content(chunk_size=8192): if chunk: f.write(chunk) return filename except Exception as e: print(f"下载PDF失败: {e}") return None def spider(url): try: response = requests.get(url, timeout=10) response.raise_for_status() except requests.RequestException as e: print(f"请求失败:{e}") return None res = {'title': '', 'author': '', 'subject': ''} soup = BeautifulSoup(response.text, 'html.parser') title_ele = soup.find(class_='title mathjax') if title_ele: res['title'] = title_ele.get_text().replace("Title:", '').strip() authors_ele = soup.find(class_='authors') authors = [] if authors_ele: links = authors_ele.find_all('a') for link in links: authors.append(link.get_text()) res['author'] = ';'.join(authors) subject_ele = soup.find(class_='tablecell subjects') if subject_ele: res['subject'] = subject_ele.get_text().strip() pdf_link = soup.find('a', text='View PDF') if pdf_link: pdf_url = 'https://arxiv.org' + pdf_link['href'] pdf_path = download_pdf(pdf_url, res['title']) if contains_keyword(res['title'], keywords) or contains_keyword(res['subject'], keywords): return res else: return None def get_information(): with open('2024.md') as f: texts = f.readlines()[2:] reses = [] target_num = 100 for text in tqdm(texts): if not contains_keyword(text, keywords): continue abs_url = re.findall(r'\[.*?\]\((https?://arxiv.*?)\)', text) if abs_url: res = spider(abs_url[0]) if res is not None: reses.append(res) print(f"已保存 {len(reses)} 篇相关论文") if len(reses) >= target_num: print(f"已保存{target_num}篇相关论文,停止爬取。") break time.sleep(5) with open('test.txt', 'w') as f: json.dump({"data": reses}, f) def write_into_table(): with open('test.txt', 'r') as f: data = json.load(f) data = data['data'] conn = sqlite3.connect('papers.db') cursor = conn.cursor() cursor.execute(''' CREATE TABLE IF NOT EXISTS papers ( id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT UNIQUE, author TEXT, subject TEXT ) ''') for paper in data: try: cursor.execute(''' INSERT OR IGNORE INTO papers (title, author, subject) VALUES (?, ?, ?) ''', (paper['title'], paper['author'], paper['subject'])) except sqlite3.Error as e: print(f"插入数据库错误:{e}") conn.commit() conn.close() if __name__ == "__main__": get_information() write_into_table() 上述代码是根据获取的信息,创建对应的医学数据库信息,并把记录信息写入,用于 SQL Call 查询。现在完成数据准备,我们得到了医学数据库文件papers.db 。 下面是获取到的PDF: 依赖模块详解 🧭 意图识别:RAG 路上的第一道分水岭 在复杂的多模态 RAG 系统中,第一步当然是搞清楚用户到底想问什么!这个模块的职责就是读取用户的提问内容(包括上下文),判断他们的意图属于哪一类: 是走传统的知识问答路线?📚 还是涉及结构化数据处理的统计问答?📊 为此,我们使用了 LazyLLM 内置的意图识别工具 —— IntentClassifier 它能智能识别用户的文本输入和上下文,快速对齐到系统预设的意图类型,让后续处理路径不再迷路,稳准狠地走向正确流程 ✅ import lazyllm from lazyllm.tools import IntentClassifier classifier_llm = lazyllm.OnlineChatModule(source="qwen") chatflow_intent_list = ["论文问答", "统计问答", "普通医疗问诊","CT医疗问诊"] classifier = IntentClassifier(classifier_llm, intent_list=chatflow_intent_list) classifier.start() print(classifier('论文中的weighted ILI 是什么?')) # 输出 >>> 论文问答 print(classifier('查询数据库中有多少篇论文')) # 输出 >>> 统计问答 print(classifier('医生,我最近总是头晕,是怎么回事?')) # 输出 >>> 医疗问诊 print(classifier('医生,我最近做了一次胸部 CT,报告上写着‘右肺上叶磨玻璃结节’,这个是什么意思?严重吗?需要进一步检查或治疗吗?')) # 输出 >>> CT医疗问诊 🧠 SQL Pipeline:结构化问答的“最强大脑” 🛠️ SQL Manager —— 数据库的超级管家 数据库管理模块 SQL Manager 基于Python 中主流的 ORM 框架——SQLAlchemy。其提供了统一的数据库操作接口,不仅支持本地数据库,也支持各种主流云数据库,极大地提升了数据库交互的灵活性和可扩展性。通过SQLManager,用户可以非常简单地连接本地或云上的数据库,只需在配置中指定数据库地址、账号密码等信息,就可以一键启动: 数据库交互能力 统一调用 SQL 查询 执行 SQL-Call 相关操作 这个模块让数据库不再是“难啃的骨头”,而是贴心的“数据服务员”。 from lazyllm.tools import SqlManager # 连接本地医学数据库 sql_manager = SqlManager("sqlite", None, None, None, None, db_name="papers.db", tables_info_dict=table_info) # 连接远程数据库 # sql_manager = SqlManager(type="PostgreSQL", user="", password="", host="",port="", name="",) # 查询所有论文数量 res = sql_manager.execute_query("select count(*) as total_papser from papers;") print("rrr: ", res) # >>> [{"total_papser": 100}] # 查询带有 LLM 的论文标题 res = sql_manager.execute_query("select title from papers where title like '%disease%'") print("res:: ", res) # >>> [{"title": "A Machine Learning Approach for Crop Yield and Disease Prediction Integrating Soil Nutrition and Weather Factors"}, {"title": "An early warning indicator trained on stochastic disease-spreading models with different noises"}, {"title": "Enhancing Gait Video Analysis in Neurodegenerative Diseases by Knowledge Augmentation in Vision Language Model"}, {"title": "Exploring the Generalization of Cancer Clinical Trial Eligibility Classifiers Across Diseases"}, {"title": "Leave No Patient Behind: Enhancing Medication Recommendation for Rare Disease Patients"}] 注意,db_name 参数需要传入构建好的数据库文件路径,tables_info_dict 参数需传入数据库基本信息字典(表名、列名等),我们以论文数据库为例,基本信息的定义如下。 table_info = { "tables": [{ "name": "papers", "comment": "论文数据", "columns": [ { "name": "id", "data_type": "Integer", "comment": "序号", "is_primary_key": True, }, {"name": "title", "data_type": "String", "comment": "标题"}, {"name": "author", "data_type": "String", "comment": "作者"}, {"name": "subject", "data_type": "String", "comment": "领域"}, ], }] } 💬 SQL Call —— 把自然语言变成数据库语言的魔法师 统计问答的第一步:当然是拿到正确的数据! 这一步交给了 SQL Call 模块,它在 SQL Manager 的基础上完成了两个关键任务: 指定目标数据库和数据表,创建 sql_manager; 实例化一个 LLM,让它具备“理解人话+写 SQL”的能力。 随后,这二者组成一个 SQL Call 工作流,能将用户的自然语言问题 ⏩ 转换成可执行的 SQL 查询,并返回结果 。 你只需要提问,系统就能代你“动手动脑”,帮你查数、汇总、返回答案! import lazyllm from lazyllm.tools import SqlManager, SqlCall sql_manager = SqlManager("sqlite", None, None, None, None, db_name="papers.db", tables_info_dict=table_info) sql_llm = lazyllm.OnlineChatModule() sql_call = SqlCall(sql_llm, sql_manager, use_llm_for_sql_result=False) query = "库中一共多少篇文章" print(sql_call(query)) # >>> [{"total_papers": 100}] 🤖 Agent 全流程 —— 数据分析 + 图表生成,一步到位 我们还基于 SQL Call 构建了一个全能型 Agent,具备: 📌 数据库查询 → 数据分析 → 图表生成 → 结果汇总 的完整能力闭环。 也就是说,用户只需一句问题,Agent 就能自动完成整个流程,从查数到出图,一条龙服务!!! 首先定义两个工具(Tool),分别用于 SQL 查询 和 代码执行,并将它们作为可选工具提供给 Agent,支持其在执行任务过程中完成数据库查询和统计分析。这两个工具配合使用,使 Agent 能够动态完成从数据获取到分析执行的全流程任务。 Tool1:run_sql_query 方法基于前面构建的 SQL Call 工作流封装而成,Agent 可在从用户查询中解析出 SQL 相关需求后调用该方法,获取结构化查询结果。 @fc_register("tool") def run_sql_query(query: str): """ Translates a natural language data request into SQL, executes it, and returns structured results. Args: query (str): A natural language description of the desired database query. Returns: list[dict]: A list of records returned from the SQL query, where each record is represented as a dictionary. """ sql_manager = SqlManager("sqlite", None, None, None, None, db_name="papers.db", tables_info_dict=table_info) sql_llm = lazyllm.OnlineChatModule(stream=False) sql_call = SqlCall(sql_llm, sql_manager, use_llm_for_sql_result=False) return sql_call(query) Tool2: run_code 用于接收并执行大模型生成的统计分析代码。该方法会返回执行结果为大模型下一步的决策和行动提供反馈依据 @fc_register("tool") def run_code(code: str): """ Run the given code in a separate thread and return the result. Args: code (str): code to run. Returns: dict: { "text": str, "error": str or None, } """ result = { "text": "", "error": None, } def code_thread(): … thread = threading.Thread(target=code_thread) thread.start() thread.join(timeout=10) … return result 接下来实现agent定义,使用lazyllm内置的ReactAgent工具,将前文中定义的两个工具传入tools参数,即可实现模型自动调用。 ReactAgent是按照 Thought->Action->Observation->Thought...->Finish 的流程一步一步的通过LLM和工具调用来显示解决用户问题的步骤,最后输出最终答案。 from lazyllm.tools.agent import ReactAgent agent = ReactAgent( llm=lazyllm.OnlineChatModule(stream=False), tools=['run_code', 'run_sql_query'], return_trace=True, max_retries=3, ) 完整代码如下: with pipeline() as sql_ppl: sql_ppl.formarter = lambda query: sql_prompt.format(query=query, image_path=IMAGE_PATH) sql_ppl.agent = ReactAgent( llm=lazyllm.OnlineChatModule(stream=False), tools=['run_code', 'run_sql_query’], return_trace=True, max_retries=3, ) sql_ppl.clean_output = lazyllm.ifs(lambda x: "Answer:" in x, lambda x: x.split("Answer:")[-1], lambda x:x) if __name__ == '__main__': lazyllm.WebModule(sql_ppl, port=23456, static_paths=image_save_path).start().wait() ⚔️ RAG Pipeline:多模态知识问答的“升级打怪”之路 这部分我们聚焦在医学论文问答场景,结合文本+图像的多模态输入,构建一个更智能的 RAG 系统,并支持返回可视化图表。整体框架的细节如下: 首先,我们将PDF解析成文本和图像;文本部分我们可以通过\n切分、LLM(总结)和 LLM(QA)等方式构造不同的block文本节点;图像部分我们通过多模态大模型构建相应的QA文本节点qapair_img和图像根节点;接下来,我们将所有节点统一编码入库,并通过多路召回机制进行语义匹配与内容检索;在召回阶段之后,引入重排序机制,进一步优化检索结果的相关性与准确性;最后,系统会将用户的查询(query)与召回得到的上下文(context)内容一并输入至多模态大模型,由其生成最终答案。整体代码实现如下: embed_mltimodal = lazyllm.TrainableModule("colqwen2-v0.1") embed_text = lazyllm.TrainableModule("bge-m3") embeds = {'vec1': embed_text, 'vec2': embed_mltimodal} qapair_llm = lazyllm.LLMParser(lazyllm.OnlineChatModule(stream=False), language="zh", task_type="qa") qapair_img_llm = lazyllm.LLMParser( lazyllm.OnlineChatModule(source="sensenova", model="SenseNova-V6-Turbo"), language="zh", task_type="qa_img") summary_llm = lazyllm.LLMParser(lazyllm.OnlineChatModule(stream=False), language="zh", task_type="summary") documents = lazyllm.Document(dataset_path=tmp_dir.rag_dir, embed=embeds, manager=False) documents.add_reader("*.pdf", MagicPDFReader) documents.create_node_group(name="block", transform=lambda s: s.split("\n") if s else '') documents.create_node_group(name="summary", transform=lambda d: summary_llm(d), trans_node=True) documents.create_node_group(name='qapair', transform=lambda d: qapair_llm(d), trans_node=True) documents.create_node_group(name='qapair_img', transform=lambda d: qapair_img_llm(d), trans_node=True, parent='Image') with lazyllm.pipeline() as ppl: with lazyllm.parallel().sum as ppl.mix: with lazyllm.pipeline() as ppl.mix.rank: with lazyllm.parallel().sum as ppl.mix.rank.short: ppl.mix.rank.short.retriever1 = lazyllm.Retriever(documents, group_name="summary", embed_keys=['vec1'], similarity="cosine", topk=4) ppl.mix.rank.short.retriever2 = lazyllm.Retriever(documents, group_name="qapair", embed_keys=['vec1'], similarity="cosine", topk=4) ppl.mix.rank.short.retriever3 = lazyllm.Retriever(documents, group_name="qapair_img", embed_keys=['vec1'], similarity="cosine", topk=4) ppl.mix.rank.reranker = lazyllm.Reranker("ModuleReranker", model="bge-reranker-large", topk=3) | bind(query=ppl.mix.rank.input) ppl.mix.retriever4 = lazyllm.Retriever(documents, group_name="block", embed_keys=['vec1'], similarity="cosine", topk=2) ppl.mix.retriever5 = lazyllm.Retriever(documents, group_name="Image", embed_keys=['vec2'], similarity="maxsim", topk=2) ppl.prompt = build_vlm_prompt | bind(_0, ppl.input) ppl.vlm = lazyllm.OnlineChatModule(source="sensenova", model="SenseNova-V6-Turbo").prompt(lazyllm.ChatPrompter(gen_prompt)) lazyllm.WebModule(ppl, port=range(23468, 23470), static_paths=get_image_path()).start().wait() 注意:由于在RAG中我们这里采用了多路召回,summary、qapair、qapair_img等节点组所在的路都会调用大模型,所以知识库越大的话,那么所消耗的时间和token都会很大,建议知识库中可以先用一两篇论文做尝试(论文中需要带图片)。 效果展示: 📈 多模态 + 统计分析:双剑合璧,能力翻倍! 在已有的多模态论文问答系统基础上,我们进一步集成了统计分析机制,让系统不仅能“看图识意”,还能“分析数据、输出结论”。这样一来,系统就不仅仅是一个问答助手,更像是一个拥有知识库+分析大脑+视觉理解力的超级 AI 学者 🤓。主要实现代码如下: def build_paper_assistant(): llm = OnlineChatModule(source='qwen', stream=False) vqa = lazyllm.OnlineChatModule(source="sensenova",\ model="SenseNova-V6-Turbo").prompt(lazyllm.ChatPrompter(gen_prompt)) with pipeline() as ppl: ppl.ifvqa = lazyllm.ifs( lambda x: x.startswith('<lazyllm-query>'), vqa, lambda x:x) with IntentClassifier(llm) as ppl.ic: ppl.ic.case["论文问答", paper_ppl] ppl.ic.case["统计问答", sql_ppl] return ppl if __name__ == "__main__": main_ppl = build_paper_assistant() lazyllm.WebModule(main_ppl, port=23494, static_paths="./images", encode_files=True).start().wait() 四、LlamaFactory 微调:让大模型「持证上岗」 通过前面的实战我们已经看到,多模态 + BI 的复杂 RAG 架构如同为大模型搭建了一套「专业工作流」—— 从图像解析到数据检索,从意图识别到 SQL 生成,让 AI 在复杂任务中实现了流程化协作。 🤔但你有没有想过,当大模型进入专业领域时,就像新手入职需要培训一样,也需要「特训」才能精准上岗?在医疗、法律等专业领域,大模型如何从「都会一点」变成「专业能手」?这一节我们就来揭秘 LlamaFactory 微调的神奇魔法,让大模型轻松拿捏专业场景! 微调:大模型的「特训营」,能力狂飙升级 在 RAG 架构里,大模型就像团队的「大脑担当」,它的能力直接决定了整个系统的输出质量。但通用大模型就像「全科生」,遇到医疗、金融等专业领域时,难免会「水土不服」。别担心!针对性的微调策略就是「特训秘籍」,能让大模型快速适应领域需求,输出更规范、更专业,堪称 RAG 系统的「神助攻」! 举个医疗领域的例子🌡️:当医生面对「患者表现出高血压症状,收缩压为 150mmHg」这样的医疗报告时,需要将其转换成包含症状、血压读数等关键信息的 JSON 格式。如果让没经过微调的通用模型来做,可能会漏信息、格式出错,甚至误解专业术语。但经过微调的大模型,就能像「专业书记员」一样,精准搞定! 🎯 微调带来的「超能力」,每一项都很能打! 精确信息提取:火眼金睛揪出关键数据📝微调就像给模型装上「信息探测器」,再也不怕重要信息「躲猫猫」!​ 上下文理解:前后逻辑全吃透🔍自然语言里,一句话的意思往往和上下文紧密相关。微调后的模型能「读懂」这些隐藏的逻辑,转换信息时更贴合实际场景,再也不是「断章取义」的憨憨啦!​ 格式严格把关:强迫症患者的福音📄JSON 等结构化文本就像「规范考场」,格式错误直接「不及格」。微调能让模型严格遵守格式要求,生成的文本就像「印刷体」一样工整!​ 术语专业处理:秒变领域「本地人」⚕️医疗领域的「收缩压」「舒张压」,金融领域的「市盈率」「复利」…… 这些专业术语就像领域的「方言」。微调让模型熟悉「行业黑话」,交流起来毫无障碍,再也不会闹「术语笑话」啦! 实战!用 LlamaFactory 给医疗模型「特训」 说了这么多,到底怎么操作呢?别急,这就带你用 LlamaFactory 实现医疗领域的 LoRA 微调,让模型从「门外汉」变身「医疗小能手」! 我们先选一个「潜力股」小模型,用权威的 Huatuo Llama Med Chinese 数据集来特训。以前的通用模型虽然能回答医疗问题,但专业术语用得不准、临床推理也不够强,就像「半吊子实习生」。现在通过权威医学对话数据的「魔鬼训练」,模型能严格按照医学证据回答,术语准确、逻辑严谨,完全符合临床规范,妥妥的「专业医师助手」! 整体微调步骤如下: 📚 第一步:准备「医学教材」—— 数据集 🌟 数据集:医学知识的「超级题库」 我们选用Huatuo Llama Med Chinese数据集(https://github.com/SCIR-HI/Huatuo-Llama-Med-Chinese/tree/main/data),该数据集由8658个问题组成,这些问题是通过医学知识图谱和GPT-3.5 API构建而成,包含大量基于中文医学知识的指令-响应对,覆盖疾病诊断、药物信息、健康咨询等场景,旨在提升LLM在医疗领域的问答与对话能力。 🧩数据结构:病例诊断的「标准模板」 数据集里的每个「知识点」长啥样?举个🌰: { "instruction": "小王,男性,45岁,近期出现上腹部隐痛、嗳气和隐痛,伴有恶心、呕吐,实验室检查发现血淀粉酶升高。请问可能患上了什么疾病?如何诊治?", "input": "", "output": "根据症状情况和实验室检查结果,考虑可能是十二指肠憩室引起的急性胰腺炎。建议进行X线钡餐检查、CT检查或十二指肠镜检查确诊。治疗原则为禁食、控制炎症、解除痉挛、液体支持等,同时给予相应的药物治疗,如抗生素、止痛药、抗酸药等。严重者需要手术治疗。" } 数据格式完全符合 Alpaca 指令微调的「万能拼图模板」,不用改格式就能直接用,简直是「懒人福音」 📜 Alpaca指令微调数据格式 Alpaca格式是一种用于指令微调的数据格式,它包含了指令、输入、输出、系统提示词和历史对话等信息。该格式适用于单轮和多轮对话场景,允许模型根据历史信息生成更准确的回答。 [ { "instruction": "人类的指令(必填)", "input": "额外的输入信息(选填)", "output": "模型的回答(必填)", "system": "系统的提示词(选填)", "history": [ ["第一轮的指令(选填)", "第一轮的回答(选填)"], ["第二轮的指令(选填)", "第二的轮回答(选填)"] ] } ] 🚀 第二步:给问题加个「模板滤镜」—— 数据处理 我们从原数据集中抽取出instruction字段与模板进行拼接,模板是:"下面是一个问题,运用医学知识来正确回答提问.\n{instruction}\n\n\n### 回答:\n"。 template = "下面是一个问题,运用医学知识来正确回答提问.\n{instruction}\n\n\n### 回答:\n" def build_train_data(data): """Format training data using predefined template""" extracted_data = [] for item in data: extracted_item = { "instruction": template.format(instruction=item["instruction"]), "input": "", "output": item["output"] } extracted_data.append(extracted_item) return extracted_data 我们取处理后的一条数据如下: [ { 'instruction': '下面是一个问题,运用医学知识来正确回答提问.\n一名年龄在70岁的女性,出现了晕厥、不自主颤抖、情绪不稳等症状,请详细说明其手术治疗和术前准备。\n\n\n### 回答:\n', 'input': '', 'output': '该病需要进行电极导线、脉冲发生器和永久心脏起搏器置入术,并需要使用镇静药物和局麻对病人进行手术治疗。术前准备包括1-3天的时间进行术前检查和生活方式的调整。' }, ... 为了测评微调后的模型效果,我们需要将数据集切分为训练集和测试集并保存,切分比例为9:1。 from sklearn.model_selection import train_test_split train_data, test_data = train_test_split(extracted_data, test_size=0.1, random_state=42) with open(train_output_path, 'w') as f: for item in train_data: f.write(json.dumps(item, ensure_ascii=False) + '\n') with open(test_output_path, 'w') as f: for item in test_data: f.write(json.dumps(item, ensure_ascii=False) + '\n') ⚙️ 第三步:给模型定制「训练计划」—— 微调模型 数据准备好了,该让模型「开练」啦! 微调相关配置代码主要如下所示: import lazyllm from lazyllm import finetune, deploy, launchers model = lazyllm.TrainableModule(model_path)\ .mode('finetune')\ .trainset(train_data_path)\ .finetune_method((finetune.llamafactory, { 'learning_rate': 1e-4, 'cutoff_len': 5120, 'max_samples': 20000, 'val_size': 0.05, 'per_device_train_batch_size': 2, 'num_train_epochs': 2.0, 'launcher': launchers.sco(ngpus=8) }))\ .prompt(dict(system='You are a helpful assistant.', drop_builtin_system=True))\ .deploy_method(deploy.Vllm) model.evalset(test_data) model.update() 上面代码中,使用LazyLLM的TrainableModule来实现:微调->部署->推理: 模型配置: model_path指定了我们要微调的模型,这里我们用Internlm2-Chat-7B,直接指定其所在路径即可; 微调配置: -.mode设置了启动微调模式finetune; -.trainset 设置了训练用的数据集路径; -.finetune_method 设置了用哪个微调框架及其参数,这里传入了一个元组(只能设置两个元素): ➡️第一个元素指定了使用的微调框架是Llama-Factory:finetune.llamafactory ➡️第二个元素是一个字典,包含了对该微调框架的参数配置 推理配置: .prompt 设置了推理时候用的Prompt,注意,这里为了和微调的Prompt中的system字段保持一致,所以开启drop_builtin_system以将原system-prompt给替换为`You are a helpful assistant.`; .deploy_method 设置了部署用的推理框架,这里指定了vLLM这个推理框架。 评测配置: 这里通过.evalset来配置评测集; 启动任务: .update 触发任务的开始:模型先进行微调,微调完成后模型会部署起来,部署好后会自动使用评测集全部都过一遍推理以获得结果。 微调loss曲线: 🏆 第四步:「成果验收」检实力 —— 效果评测 在上一步微调并获得评测集的推理结果后,我们需要拿着结果和评测集的正确答案做个对比,以确认我们微调的效果是什么样的。 在这个任务当中,我们使用语义相似度来评测模型的效果。语义相似度定义如下: 相应的代码实现如下,这里不含求平均,只是其中一项,同时假设文本已经被BGE模型(bge-large-zh-v1.5)向量化了: import numpy as np def cosine(x, y): product = np.dot(x, y) norm = np.linalg.norm(x) * np.linalg.norm(y) raw_cosine = product / norm if norm != 0 else 0.0 return max(0.0, min(raw_cosine, 1.0)) 在共866题的测试集中,模型Internlm2-Chat-7B微调前后的语义相似度如下所示: Internlm2-Chat-7B 微调前 微调后 语义相似度 63.98% 76.96% ✨ 微调效果展示 微调前: { "question": "下面是一个问题,运用医学知识来正确回答提问.\n王女士,45岁,近日出现面部疼痛,伴有刺痛感和头皮肿胀,且左侧面部出现营养性溃疡,有角膜结痂和发痒症状,初步诊断为何种疾病?\n\n\n### 回答:\n", "true_answer": "根据临床表现,该患者初步诊断为三叉神经营养性损害。需要进一步检查确定病因。", "prediction": "根据王女士的症状描述,她可能患有一种称为带状疱疹的疾病,也称为水痘-带状疱疹病毒感染。带状疱疹是由水痘-带状疱疹病毒(Varicella-Zoster Virus,VZV)引起的,这种病毒初次感染人体时会导致水痘,随后潜伏在神经系统中。在免疫系统减弱或老化时,病毒可能会重新激活,导致带状疱疹。\n\n以下是带状疱疹的典型症状和王女士描述的症状的对应情况:\n\n1. **面部疼痛**:带状疱疹可引起神经痛,王女士描述了面部疼痛。\n2. **刺痛感和头皮肿胀**:这种疼痛通常为灼烧感、刺痛感和麻木感,并可能伴随着头皮肿胀。\n3. **营养性溃疡**:带状疱疹可以导致皮肤溃烂,形成溃疡。\n4. **角膜结痂和发痒症状**:带状疱疹病毒感染也可能影响眼睛,导致角膜结痂和发痒。\n\n初步诊断为带状疱疹是基于这些症状的相似性。然而,为了确诊,医生可能会进行进一步的检查,如皮肤拭子检查、血液检查或神经功能测试。\n\n治疗带状疱疹通常包括使用抗病毒药物来减轻症状和缩短病程,以及疼痛管理,如非处方药、处方药、物理疗法或神经阻滞剂。对于营养性溃疡和角膜结痂,医生可能会建议局部治疗或抗生素治疗以预防感染。\n\n请记住,这只是一个初步诊断,确诊应由医疗专业人员进行。如果您或您认识的人有类似的症状,请及时就医以获得适当的治疗。", "cosine_score": 0.32186800394435827 } 微调后: { "question": "下面是一个问题,运用医学知识来正确回答提问.\n王女士,45岁,近日出现面部疼痛,伴有刺痛感和头皮肿胀,且左侧面部出现营养性溃疡,有角膜结痂和发痒症状,初步诊断为何种疾病?\n\n\n### 回答:\n", "true_answer": "根据临床表现,该患者初步诊断为三叉神经营养性损害。需要进一步检查确定病因。", "prediction": "根据病例描述,初步诊断为三叉神经营养性损害。建议进行进一步检查以确定病因,并采取适当的治疗方案。", "cosine_score": 0.9675316856997899 } 五、用 LlamaFactory 玩转多模态 RAG 模型微调🎯 在上一节中,我们已经见证了通过 LlamaFactory 微调让大模型在医疗文本领域「持证上岗」的魔力。而对多模态模型进行微调,能够有效提升模型在特定多模态领域的适应能力。 例如,在医学图像领域,基于多模态模型实现简单的诊断。甚至就不需要额外上下文信息。 当医生拿着CT片问AI:"这片脑区有梗塞吗?" 普通AI:"抱歉,我无法提供诊断建议" ❌(急死个人!) ​​LlamaFactory微调后的AI​​:"右侧基底节区可见低密度灶,考虑急性梗塞" ✅(专业!) ​​想知道怎么让AI从"小白"变身"影像科大神"吗?​​ 跟我一起探索吧! 🔧数据集简介 VQA-RAD 是一个关于放射影像的问题-答案对数据集(https://huggingface.co/datasets/flaviagiammarino/vqa-rad )。 训练集 测试集 问题 1,793 451 图像 313 203 🚀 数据集用途 训练和测试医学影像VQA(视觉问答)系统 支持开放式问题(如“病灶位置?”)和二元问题(如“是否存在肿瘤?”) 🔍 数据来源 基于MedPix(开放医学影像数据库) 由临床医生手动标注,确保专业性 🌟 核心优势 首个专注放射影像的VQA数据集 结构清晰,覆盖临床常见问题类型 📊 数据处理 数据获取 from datasets import load_dataset dataset = load_dataset("flaviagiammarino/vqa-rad") 处理前 { "image": <PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=566x555>, "question": 'are regions of the brain infarcted?', "answer": 'yes' } 处理后(OpenAI格式): [ { "messages": [ { "content": "<image>are regions of the brain infarcted?", "role": "user" }, { "content": "yes", "role": "assistant" } ], "images": [ path/to/train_image_0.jpg" ] }, 💡微调模型 import lazyllm model_path = 'path/to/Qwen2.5-VL-3B-Instruct' data_path = 'path/to/vqa_rad_processed/train.json' # 需要将环境中的transformers和llamafactory升级到最新的开发分支 m = lazyllm.TrainableModule(model_path) .mode('finetune') .trainset(data_path) .finetune_method( (lazyllm.finetune.llamafactory,{ 'learning_rate': 1e-4, 'cutoff_len': 5120, 'max_samples': 20000, 'val_size': 0.01, 'num_train_epochs': 2.0, 'per_device_train_batch_size': 16, })) m.update() ⚒️模型配置: model_path指定了我们要微调的模型,这里我们用Qwen2.5-VL-3B-Instruct,直接指定其所在路径即可; ⚒️微调配置: .mode设置了启动微调模式finetune; .trainset 设置了训练用的数据集路径; .finetune_method 设置了用哪个微调框架及其参数,这里使用的是 llamafactory 框架(一个支持 LoRA、QLoRA 等高效微调技术的库); learning_rate:1e-4学习率,表示模型每一步更新参数的幅度。较高值训练更快但可能不稳定; cutoff_len: 5120输入序列的最大长度,超过这个长度的文本会被截断。适用于长对话或长描述任务; max_samples: 20000用于训练的最大样本数。如果你不想训练整个数据集,可以限制在一定数量; val_size: 0.01验证集占比。这里是 1%,意味着 99% 的数据用于训练,1% 用于评估模型训练过程中的性能; num_train_epochs: 2.0训练轮数。每个 epoch 表示模型看完整个训练集一次; per_device_train_batch_size: 16每个设备(通常是 GPU)上的训练批大小。根据显存大小选择合适的 batch size。 ⚒️启动任务: .update 触发任务的开始:模型先进行微调,微调完成后模型会部署起来,部署好后会自动使用评测集全部都过一遍推理以获得结果。 微调loss曲线 🏆 模型评测 在共451题的测试集中,模型Qwen2.5-VL-3B-Instruct微调前后的精确匹配率和语义相似度如下所示: Qwen2.5-VL-3B-Instruct 微调前 微调后 精确匹配率 0.0% 55.43% 语义相似度 31.85% 80.64% 📌精确匹配度 我们将精确匹配度定义如下: 其中: N:测试样本总数; yi:第i个样本的标准答案; yi^:模型预测结果; Ⅱ:指示函数(完全匹配时取1,否则取0)。 该指标的特性在于:预测结果与标准答案需要完全一致。 📌语义相似度 我们将语义相似度定义如下: 其中: N:测试样本总数; yi:第i个样本的标准答案; yi^:模型预测结果; emb():是基于BGE模型(bge-large-zh-v1.5)的向量编码,它可以把自然语言编码为一个向量,即:emb(text)=BGE_Encoder(text)。 🚨注意:该评价指标将原本[-1,0)的数值进行了截断,只要是负相关的语义都给0分,得分只能是正相关的。 示例:针对如下影像,微调前后的输出 微调前: { "query": "is the liver visible in the image?", "true": "no", "infer": "yes, the liver is visible in the image. it appears as a large, dark gray structure located in the upper left quadrant of the abdomen.", "exact_score": 0, "cosine_score": 0.3227266048281184 } 微调后: { "query": "is the liver visible in the image?", "true": "no", "infer": "no", "exact_score": 1, "cosine_score": 1.0 } 🤖 CT医疗诊断助手 模型「魔鬼训练」完毕,已经从「半吊子实习生」晋升为「专业医师助手」!那接下来,怎么让它真的派上用场?答案就是——构建医疗知识库 + RAG 检索增强生成,让模型不止「会说」,更能「精准说」! 我们来一步步操作,带你搭建一个属于你的CT医疗诊断助手,让模型不再孤军奋战,而是背后站着一整个医疗知识库做后盾! 🧠 整理知识库——医学资料大合集 我们选用Huatuo-Lite数据集(https://huggingface.co/datasets/FreedomIntelligence/Huatuo26M-Lite ),这是目前最大的中文医疗问答数据集,这些问答对通过文本清洗和数据去重的方法,从多个来源精心收集而来,包括在线医疗咨询网站、医学百科全书和医学知识库,覆盖了广泛的医疗知识。该数据集的创建显著扩大了医疗领域问答数据集的规模,并为中文医疗领域的自然语言处理和人工智能研究提供了一个前所未有的资源。 通过如下代码,我们可以获取数据,构建知识库: from datasets import load_dataset # 下载数据集 ds = load_dataset("FreedomIntelligence/Huatuo26M-Lite", split="train") output_path = "huatuo_cleaned.txt" count = 0 with open(output_path, "w", encoding="utf-8") as f: for sample in ds: question = sample.get("question", "").strip().replace("\n", " ") answer = sample.get("answer", "").strip().replace("\n", " ") diseases = sample.get("related_diseases", []) if isinstance(diseases, list): diseases = ", ".join([d.strip() for d in diseases]) else: diseases = diseases.strip() if question and answer: line = f"Question: {question}\tAnswer: {answer}\tRelated Diseases: {diseases}" f.write(line + "\n") count += 1 print(f"✅ 数据处理完成,共写入 {count} 条记录 -> {output_path}") 🧪 实现RAG——模型+知识双保险 📌 原理:输入(用户带CT提问+微调后的VQA的初诊结果) → 向量检索相关医学知识 → 与输入拼接 → 喂给模型生成回答。 RAG 就像给模型配了「助理医生」,先去查资料,再结合自身能力回答,大大提升准确率和可信度。我们对输入的QA对进行拼接,并要求大模型根据提供的问题和CT影像的初步诊断结果,结合知识库召回结果进行回答: import lazyllm #加载知识库 documents = lazyllm.Document(dataset_path="./kb") documents.create_node_group(name="block", transform=lambda s: s.split("\n") if s else '') #构建检索器 retriever = lazyllm.Retriever( doc=documents, group_name="block", # 分组方式可自定义 similarity="bm25_chinese", # 中文 BM25 向量检索 topk=5 # 召回前5条问答作为上下文 ) #加载 LLM 组件(可以选用适配医学任务的模型) llm = lazyllm.OnlineChatModule(source="qwen", model="qwen-max-latest", stream=False) #设计提示词 prompt = ( "你是一个专业的医学问答助手,用户会提供问题和CT影像的初步诊断结果,以及用来补充参考的医学知识。" "请根据用户提供的信息给出相关的诊断结果和治疗建议,若用户不存在问题可以不用给出治疗建议。\n\n" "注意:如果资料中没有明确提到答案,也请你基出于医学常识尽力做解释。\n\n" ) llm.prompt(lazyllm.ChatPrompter(instruction=prompt, extra_keys=['context_str'])) 最后构建输入并执行问答: #检索文档内容作为上下文 doc_node_list = retriever(query=query) context = "".join([node.get_content() for node in doc_node_list]) #构建输入 & 执行问答 response = llm({ "query": query, "context_str": context }) #输出最终回答 print(f"Query: {query}\n") print("📘 检索到的知识片段:\n") for i, node in enumerate(doc_node_list, 1): print(f"[{i}] {node.get_content()}\n") print("💡 回答:") print(response) 🔍 效果展示 🚀 input:下面是CT医疗问诊的问题以及CT图像初步诊断。问题:does the gallbladder appear distended?;图像初步诊断:yes; 🧰 output: 可以看到小助手召回了相关片段并给出了回答! 通过微调+RAG,LLM不再「闭门造车」,而是真正拥有了「读万卷书 + 亲临临床」的实力,成为你身边靠谱的「AI 医学助理」! 要不要试试看搭一个属于你自己的智能医疗顾问? 六、多模态 + BI + 医疗落地:打造懂医学的 RAG 系统 🩺 基于前面多模态与 BI 能力的深度融合实践,我们进一步将 RAG 系统向医疗垂直场景做了进阶升级 —— 如今这套架构不仅能处理常规的文本问诊,更能通过 VQA 模块与医学知识库的联动,实现 CT 影像解析与智能诊断辅助的核心能力,打通了从临床咨询到辅助决策的全流程服务闭环。下面就带大家看看这套融合多模态理解、数据统计与专业知识的医疗 RAG 系统是如何落地的! 主要实现代码如下: # 搭建具备知识问答和统计问答能力的主工作流 def build_paper_assistant(): llm = OnlineChatModule(source='qwen', stream=False) with pipeline() as ppl: ppl.ifvqa = lazyllm.ifs( lambda x: x.startswith('<lazyllm-query>'), vqa_ppl, lambda x:x) with IntentClassifier(llm) as ppl.ic: ppl.ic.case["论文问答", paper_ppl] ppl.ic.case["统计问答", sql_ppl] ppl.ic.case["普通医疗问诊", inquiry_ppl] ppl.ic.case["CT医疗问诊", ct_ppl] return ppl if __name__ == "__main__": main_ppl = build_paper_assistant() lazyllm.WebModule(main_ppl, port=23494, static_paths="./images", encode_files=True).start().wait() 在这篇文章中,我们带您从朴素 RAG 出发,逐步走向具备多模态感知与 BI 能力的复杂智能问答系统,结合了 LlamaFactory 的微调实践,全面展现了多模态 RAG 的落地路径。但这只是开始——更多技术细节,欢迎移步LazyLLM gzh讨论!

优秀的个人博客,低调大师

从对话到自主行动:AI应用如何从 Chat 进化为 Agent?开源项目源码深度揭秘|得物技术

一、引言 从2022年12月份OpenAI发布ChatGPT产品至今已有2年多的时间,当大家已经习惯于在对话框中与AI交互,习惯于通过各种Prompt技巧让AI更好的理解并回答我们的问题,似乎默认这就是一种比较好与AI的交互方式了。 然而,这就是我们期盼的与AI交互的形式嘛?这是一种高效的方式嘛? 显然,这是不够的。 我们期望的是:告诉AI我们想要的目标或者任务,AI能够理解深度理解并分析我们的意图、自动的进行任务的拆解、自动的寻找可以使用的工具、自动的进行结果数据的汇总过滤、自动的呈现符合任务的展示形式。同时在任务处理过程中,可以自己完成异常的检测和修改。就如同一位优秀的同学,我们告诉他任务的目标,他可以自己寻找飞书文档、搜索网络知识、使用内部系统、自己编码验证方案可行性,并最终给一份好的解决方案。 二、以「对话为中心」的ChatBot 我们发送一条指令,AI被动的响应指令。即完成一轮人与AI的交互。 具体视频请前往“得物技术”微信公众号观看。 三、以「交付为中心」的多智能体Agent 我们发送一个任务,AI自动分析任务、调用可用的工具、分析结果、过滤数据并自动处理异常,最终呈现解决方案。 完成这样的一个任务,需要多智能体Agent间的协作以及对常用工具的调用。那什么是智能体Agent呢? 具体视频请前往“得物技术”微信公众号观看。 四、什么是智能体Agent 从Prompt到思维链 随着大模型的发展,Prompt工程已成为撬动大模型潜能的核心技术。即使我们普通用户在与大模型的交互中,也通过角色定义(如"资深工程师")或示例引导来优化输出效果,但这类简单提示往往难以突破模型固有的逻辑天花板——就像给赛车装自行车轮胎,再怎么调整也难以突破速度极限。 但偶然间,人们发现了一个神奇的咒语:只需要告诉大模型,你的 think 要 step by step。研究者发现只要加了这个prompt,就能极为显著地改善大模型做数学题的正确率。 大模型的数学与逻辑能力短板,是所有体验过其对话功能的用户都能直观感受到的痛点。这一缺陷严重制约了大模型的商业化落地进程,毕竟没有人敢轻易信任一个逻辑混乱的智能系统能输出可靠的决策结果。于是,提升大模型数学能力,被所有做基础模型的公司当作了第一目标。 研究者试图通过强化思维链来突破这一瓶颈。一个直观的思路是:让模型像人类解题时在草稿纸上推演那样,通过 "step by step" 的方式展开逻辑链条 —— 在这个过程中,包含假设、演绎、反思、纠错等一系列思维活动。既然人类通过这种结构化的思考方式能够有效解决数学问题,那么大模型是否也能通过类似机制实现能力跃迁?这一猜想推动着研究向纵深发展,最终形成了思维链技术的核心框架。这样的观念经过继续钻研,最终就构成了思维链,思维链是一个能以最小的代价,而非常显著提升模型智力水平(逻辑能力、解题能力、代码能力)的技术。 值得注意的是,2025 年春节期间引发广泛关注的 DeepSeek 大模型,正是思维链技术的成功实践典范。尽管 DeepSeek 并非首创者,但其通过创新性地融合混合专家(MoE)架构与强化学习技术,显著提升了思维链推理的计算效率与性能表现。这种技术优化使得 DeepSeek 在保持高精度推理的同时,大幅降低了计算成本,最终实现了屠榜级表现。 ReAct架构 如果说思维链(COT)是给 AI 装上了人类的 "草稿纸",那么 ReAct 框架就是为它配备了 "双手"—— 让 AI 不仅能在脑子里推演,还能主动采取行动获取信息。这种 "思考 + 行动" 的组合,正在把大模型从 "纸上谈兵" 的理论家,变成能解决现实问题的实干家。 ReAct 的核心在于将**推理(Reasoning)与行动(Action)**紧密结合。当模型面对复杂问题时,会先像人类一样拆解思考步骤,然后根据中间结果调用外部工具(如搜索引擎、数据库、计算器)获取实时数据,再把这些信息整合到后续推理中。 其实,实现一个ReAct很简单,只需要构建Prompt+提供工具+循环执行即可,笔者在这里不进行详细的介绍,只需要给一个Prompt例子,读者就能理解: 尽可能最好地为用户回答接下来的问题,你可以使用以下工具来辅助你:{tools} 使用以下格式: -问题:你需要回答的输入问题 -思考:你需要持续思考下一步采取什么行动 -行动:要采取的行动,应该是[{tool_names}]中的一个,以及该行动的输入内容 -观察:行动并观测结果,并判断结果是否合理 ...(这个思考/行动/观察可以重复 N 次,直到你认为知道了最终答案 -最终答案:原始输入问题的最终答案 开始! -问题:{input} Tools支持开发者自定义,比如给予LLM一个查询天气的接口、计算器接口等。 ReAct架构实现了一种**"问题拆解-工具调用-结果整合"的闭环机制,使得开发者仅需通过定义工具集(如天气API、计算器、知识图谱接口)和设计任务引导词,就能将大模型转化为可执行多步骤决策的智能体。最终可以使大模型突破纯文本推理的局限,真正具备了在动态场景中解决开放性问题的工程化能力。 Agent Agent作为大模型技术的集大成者,通过整合思维链(CoT)的推理能力和ReAct框架的行动机制,构建了具备自主决策与执行能力的智能系统。其核心突破在于将**“大脑”与“四肢”**有机统一,标志着大模型从被动应答迈向主动干预现实的质变。 在架构上,Agent与ReAct差别不大,ReAct是Agent的核心实现范式之一,Agent进一步整合记忆存储、多智能体协作等模块,形成更完整的自主决策系统。下图是一个简单的Agent架构图: Agent处理流程 1-4步会循环进行,直到LLM认为问题已被回答。 1.规划(Planning): 定义:规划是Agent的思维模型,负责拆解复杂任务为可执行的子任务,并评估执行策略。 实现方式:通过大模型提示工程(如ReAct、CoT推理模式)实现,使Agent能够精准拆解任务,分步解决。 2.记忆(Memory): 定义:记忆即信息存储与回忆,包括短期记忆和长期记忆。 实现方式:短期记忆用于存储会话上下文,支持多轮对话;长期记忆则存储用户特征、业务数据等,通常通过向量数据库等技术实现快速存取。 3.工具(Tools): 定义:工具是Agent感知环境、执行决策的辅助手段,如API调用、插件扩展等。 实现方式:通过接入外部工具(如API、插件)扩展Agent的能力,如ChatPDF解析文档、Midjourney文生图等。 4.行动(Action): 定义:行动是Agent将规划与记忆转化为具体输出的过程,包括与外部环境的互动或工具调用。 实现方式:Agent根据规划与记忆执行具体行动,如智能客服回复、查询天气预报、AI机器人抓起物体等。 Manus:一个Agent典型案例 在读完前一节关于智能体(Agent)的技术解析后,读者也许会认为这类系统的工程实现并非难事,实际上也确实是这样。近期爆火的 Agent 产品 Manus 便是典型案例。当用户提出 "定制 7 天日本旅行计划" 的需求时,Manus 能够基于目标,自主进行网络搜索并将信息整合,展现出高度拟人化的任务执行逻辑。 尽管 Manus 目前尚未向普通用户开放,且采用邀请制注册的封闭运营模式,但其通过官方演示视频呈现的强大智能化表现,已在技术圈引发广泛关注。值得关注的是,随着Agent技术的热度攀升,开源社区已迅速涌现出 OpenManus、OWL 等多个复刻项目。 因为Manus并非开源,我们很难了解其技术细节。但好在: "Manus 的部分技术细节,包括其提示词设计、运行机制等内容被网友通过非官方渠道披露,感兴趣的读者可自行查阅相关公开资料。 我们可以了解一下大模型上下文协议(Model Context Protocol,MCP),这是 Anthropic (Claude) 主导发布的一个开放的、通用的、有共识的协议标准,虽然Manus不一定用了这个协议,但目前一些相关开源项目也是基于MCP的,本文会在下面介绍MCP。 目前已有复刻的开源项目Openmanus,笔者会在接下来的章节剖析其源码。 大模型上下文协议(MCP) MCP是做什么的? MCP(Model Context Protocol)作为一项开放协议,旨在为应用程序与大型语言模型(LLMs)之间的上下文交互提供标准化框架。其设计理念可类比为数字时代的 "USB-C 接口"—— 正如 USB-C 统一了设备与外设的连接标准,MCP 通过标准化的上下文交互接口,实现了 AI 模型与多样化数据源、工具之间的无缝对接。 如下图所示,图中的MCP server都可以看成一个个工具(如搜索引擎、天气查询),通过“接口”连接到MCP clients(大模型)上,大模型可以使用各种MCP server来更好地处理用户的问题。 此外,下游工具的开发者也可以更好的开发其工具,目前在MCP官网即可了解其各种编程语言的SDK和相关概念。 MCP架构 MCP 的核心采用客户端-服务器架构,其中 host 可以连接到多个服务器,读者简单看看即可: MCP 主机(MCP Hosts):指需要通过 MCP 协议获取数据的应用程序,涵盖 AI 开发工具(如 Claude Desktop)、集成开发环境(IDEs)等智能应用场景。 MCP 客户端(MCP Clients):作为协议的执行者,每个客户端与对应的 MCP 服务器建立一对一的专属连接,负责协议层面的通信交互。 MCP 服务器(MCP Servers):轻量化的功能载体,通过标准化的 Model Context Protocol 对外开放特定能力,可视为连接模型与工具的智能桥梁。 本地化数据源(Local Data Sources):包括服务器可安全访问的本地文件系统、数据库及专有服务,构成数据交互的近端生态。 远程服务(Remote Services):通过互联网连接的外部系统,例如各类 API 接口服务,拓展了模型的能力边界。 为什么要用MCP? 从技术演进视角看,MCP 的诞生是提示工程(Prompt Engineering)发展的必然产物。研究表明,结构化的上下文信息能显著提升大模型的任务表现。在传统提示工程中,我们往往需要人工从数据库筛选信息或通过工具检索相关内容,再手动将这些信息注入提示词。然而,随着复杂任务场景的增多,这种手工注入信息的操作变得愈发繁琐且低效。 为解决这一痛点,主流大模型平台(如 OpenAI、Google)先后引入了函数调用(Function Call)机制。该机制允许模型在推理过程中主动调用预定义函数获取数据或执行操作,极大提升了自动化水平。然而,函数调用机制存在显著局限性:其一,不同平台的函数调用 API 存在较大差异,例如 OpenAI 与 Google 的实现方式互不兼容,开发者在切换模型时需重新编写代码,徒增适配成本;其二,该机制在安全性、交互性及复杂场景的扩展性方面仍存在优化空间。 在此背景下,MCP 协议通过标准化的上下文交互接口,为大模型构建了更具普适性的工具调用框架。它不仅解耦了模型与工具的依赖关系,还通过统一的协议规范解决了跨平台兼容性问题。更重要的是,MCP 将上下文管理提升到系统架构层面,为大模型在复杂业务场景中的深度应用提供了可扩展的技术底座。这种从碎片化的提示工程到体系化的上下文协议的演进,标志着大模型应用正在向更高效、更规范的方向迈进。 四、智能体Agent实现的源码剖析(OpenManus项目) OpenManus 是一个基于 MCP 协议的开源智能体实现项目,旨在通过标准化的上下文协议实现大模型与工具的高效协同。当前项目仍处于快速迭代阶段,本文以其 2025 年 3 月 12 日的版本为分析对象。选择该项目的原因如下: 团队背景与代码质量:项目作者来自MetaGPT,具备深厚的工程经验,代码结构清晰且注释完善,兼顾了技术实现与可读性。 部署便捷性:只需通过虚拟环境安装依赖并配置大模型 API Key(如 OpenAI 的 API 密钥),即可快速启动,降低了技术门槛。 技术前沿性:项目紧跟大模型技术发展,且目前仍在不断迭代的过程中。 在经过前面对相关概念的讨论,我们可以得知实现Agent有几个关键的点,读者可以带着问题在项目中寻找答案: Prompt:其结构化的Prompt是什么样的?通过Prompt可以对其架构有一个初步认识。 OpenManus:怎么通过大模型思考和处理问题? 工具相关:怎么进行工具注册、工具管理的?工具执行逻辑是什么的? 准备 项目地址: https://github.com/mannaandpoem/OpenManus/tree/main 构建环境 创建一个python=3.12的虚拟环境 笔者测试了一下,非3.12版本会有一个package不兼容。 可以用conda或python内置的uv,项目文档提供了详细的指令。 安装playwright 如果第一次使用,需要安装playwright。 playwright install ## 或者 python -m playwright install ## 以上命令会安装所有浏览器,如果只需要安装一个浏览器比如firefox python -m playwright install firefox 配置大模型API Key 可以用DeepSeek或通义千问的API Key,其中通义有免费额度,DeepSeek虽然收费但价格便宜,测试一次使用约1000token,成本不到0.01元。 根据项目文档配置cofig.yaml即可,但项目调用大模型是使用基础的OpenAI API,如果使用其他大模型,可能需要基于对应的官方文档小改一下。 代码 OpenManus客户端 Python OpenManus/main.py即可在终端运行OpenManus,读者也可以尝试其Web版本。 具体会调用20行代码,执行Manus类的方法run()。 进入OpenManus/app/agent/manus.py查看Manus类,可以发现它继承了ToolCallAgent类,再进入会发现又是继承,有点复杂,这里我画一张关系图。 act()执行时使用execute_tools()进行具体的工具执行。 总体来说,Manus类定义了Prompt和可使用的工具。 Base类定义了run(),在run()中会循环执行ReAct类的方法step(),直到Finish或达到max_step。 step()类会顺序执行ToolCallAgent类的think()和act()。 当然,这里只罗列了重要的组件和方法,一些方法没有画在图中。 Prompt 一般来说,输入给LLM的prompt分为两种:1)系统 prompt,用于定义模型的角色定位和行为规则;2)用户 prompt(OpenManus称为Next Step Prompt),用于传达具体的任务指令或信息需求。 在OpenManus/app/prompt/manus.py中即可看到Manus的Prompt,这里展示一下中文版,读者基于此可对OpenManus架构有一个初步认识: 系统Prompt(SYSTEM_PROMPT):“你是 OpenManus,一个全能的人工智能助手,旨在解决用户提出的任何任务。你拥有各种可使用的工具,能调用这些工具高效地完成复杂的请求。无论是编程、信息检索、文件处理还是网页浏览,你都能应对自如。” 下一步Prompt(NEXT_STEP_PROMPT):“你可以使用 PythonExecute 与计算机进行交互,通过 FileSaver 保存重要的内容和信息文件,使用 BrowserUseTool 打开浏览器,并使用 GoogleSearch 检索信息。根据用户的需求,主动选择最合适的工具或工具组合。对于复杂的任务,你可以将问题分解,逐步使用不同的工具来解决它。在使用完每个工具后,清晰地解释执行结果并给出下一步的建议。 当然,在实际执行时会对prompt有进一步优化,不过核心的系统定位与任务指导原则是不会改变的。 Manus类 我们先看一下OpenManus拥有的工具,工具也支持自定义,会在后文进行介绍。 PythonExecute:执行 Python 代码以与计算机系统交互、进行数据处理、自动化任务等等。 FileSaver:在本地保存文件,例如 txt、py、html 等文件。 BrowserUseTool:打开、浏览并使用网络浏览器。如果你打开一个本地 HTML 文件,必须提供该文件的绝对路径。 GoogleSearch:执行网络信息检索。 Terminate:如果LLM认为回答完毕,会调用这个工具终止循环。 Base类 run() 首先,输入的request就是用户输入的提问。 状态管理 执行时首先检查代理的当前状态是否为 IDLE(空闲状态)。如果不是空闲状态,会抛出 RuntimeError 异常,因为只有在空闲状态下才能启动代理的执行。 当进入循环时前,使用 state_context上下文管理器将代理的状态临时切换到 RUNNING(运行状态)。在上下文管理器中执行的代码块会在进入时将状态切换为指定状态,在退出时恢复到之前的状态。如果在执行过程中发生异常,会将状态切换为 ERROR。 Memory管理 我们调用大模型的API,本质是向大模型提供方发http请求,http请求是无状态的。 也就是说,服务端不会保留任何会话信息。对于每次都完成一个独立的任务,无状态是没有任何问题的。但对持续聊天来说,就会出现对之前会话一无所知的情况。 所以为了让大模型持续与用户的对话,一种常见的解决方案就是把聊天历史告诉大模型。 因此,在OpenManus中会进行Memory的管理。 用户提供的 request 参数,调用 update_memory 方法将该请求作为用户消息添加到代理的Memory中。 除了这个函数,Manus也在进行think()、act()时也会更新Memory,同时Memory容量也不是无限大的,容量满时需要删除老的Message。 主循环 agent本质就是循环执行。 step实现参考react step。 循环结束条件:max_steps或者FINISHED状态。 每次执行一个step并获得result——step_result = await self.step()。 is_stuck 方法用于检查代理是否陷入了循环(即是否出现了重复的响应)。如果是,则调用 handle_stuck_state 方法处理这种情况,例如添加一个提示来改变策略。 ReAct step() 这里的逻辑很简单。 ToolcallAgent Think() 输入:不需要输入,因为用户的question是被存放在Memory中。 输出:一个bool类型,当内部LLM判断需要act()时,为True,否则为Fasle。 询问LLM 55行的代码用于调用LLM的API接口,获取回复。 对应到OpenManus/app/llm.py 233行附近,这里就是基于OpenAI提供的API接口进行对话,具体的参数可参考相应官方文档。 这里会将之前定义的下一步Prompt发给LLM,LLM会根据提供的工具列表,判断是否需要且调用的是哪个工具,当然也可能是:1)不需要工具只进行回复 2)调用Terminate工具结束会话。 下图是一次返回response结果。 输入的question是“计算Kobe Bryant的BMI?”,LLM先分析出了要通过浏览器查询资料,因此要use the BrowserUseTool。 根据传入的工具类型等信息,LLM自动构建了执行工具需要用的tool_name、action等参数。 ChatCompletionMessage( content="It seems there was an issue with retrieving the information about Kobe Bryant's height and weight through a Google search. To calculate Kobe Bryant's BMI, we need his height and weight. Let's try to find this information by opening a browser and visiting a reliable source. I will use the BrowserUseTool to navigate to a website that provides details about Kobe Bryant's height and weight. Let's proceed with this approach.", refusal=None, role='assistant', annotations=None, audio=None, function_call=None, tool_calls=[ ChatCompletionMessageToolCall( id='call_aez57ImfIEZrqjZdcW9sFNEJ', function=Function( arguments='{ "action":"navigate", "url":"https://www.biography.com/athlete/kobe-bryant" }', name='browser_use'), type='function')] ) think后续逻辑 think()后续的逻辑比较简单,主要是更新memory(memory存储单位是message),最后在100行附近的逻辑,基于self.tool_choices等参数的设置和LLM返回的工具列表,输出bool类型结果。 同时,需要被调用的工具会被记录到self.tool_calls这个列表中,后续的act()会执行对应的工具。 Act() 输入:同think(),不需要输入。 输出:results,根据工具结果构建的一个字符串。 这个函数比较简单,主要是调用execute_tool()函数。 Execute_tool() 该函数会调用Tool类提供的接口execute()。 Tool类接口会在后面介绍。 同时,对于预设定的special tool,会self._handle_special_tool(name=name, result=result)进行特殊处理。 当前的special tool 只有一个Terminate工具,特殊处理就是设置Agent的状态为AgentState.FINISHED,结束对话。 工具相关 我们在之前介绍了MCP相关的概念,如下图所示: 事实上,OpenManus也是基于MCP的,OpenManus的tool相当于MCP server,根据MCP协议,我们只需要定义tool类支持的方法和参数等,每次注册一个新工具,根据父类override一个子类即可。 那我们首先要了解父类都定义了什么参数和方法,也就是OpenManus/app/tool/base.py定义的Basetool类。 Base Tool 可以看出,代码很简单,每个tool包含的参数为:name、description(提供给LLM看的,对工具的介绍)、parameters(执行工具时要用的参数)。 同时,一个tool支持的方法有execute()和to_param()。 execute()用于执行具体的逻辑,每个子类需要override这个方法。 to_param()将工具调用的结果结构化输出。 当然,这里还有一个python关键字__call__,这个关键字很简单,定义了__call__,该类的实例对象可以像函数一样被调用。 工具JSON 可以根据OpenManus预定义的工具json简单了解一下,每个工具执行时需要的参数。 [ { "type": "function", "function": { "name": "python_execute", "description": "Executes Python code string. Note: Only print outputs are visible, function return values are not captured. Use print statements to see results.", "parameters": { "type": "object", "properties": { "code": { "type": "string", "description": "The Python code to execute." } }, "required": ["code"] } } }, { "type": "function", "function": { "name": "google_search", "description": "Perform a Google search and return a list of relevant links.\nUse this tool when you need to find information on the web, get up-to-date data, or research specific topics.\nThe tool returns a list of URLs that match the search query.\n", "parameters": { "type": "object", "properties": { "query": { "type": "string", "description": "(required) The search query to submit to Google." }, "num_results": { "type": "integer", "description": "(optional) The number of search results to return. Default is 10.", "default": 10 } }, "required": ["query"] } } ] 工具示例——google_search OpenManus项目在OpenManus/app/tool中定义了bash工具、浏览器工具、谷歌搜索工具等,这里简单看一下谷歌搜索工具。 当然,国内可能比较难使用谷歌搜索,OpenManus社区也有大佬提供了baidu、bing等搜索引擎工具。 可以看出,代码很简单,主要做了两件事。 定义工具参数:name、description、parameters。 定义execute:基于googlesearch库提供的函数进行搜索并返回。 五、总结 OpenManus的代码介绍到这里,主要是介绍一下核心代码,同时,原作者写了planning部分的代码但暂时没有应用到项目中,笔者也没有介绍。如果想对该项目有更进一步的了解,请大家查看github上提供的源码。而且,作者还是非常积极的,每天会有十几个commit。 同时,读者可以简单本地部署玩一下OpenManus,通过几个prompt,就可以知道该项目还是停留在“玩具阶段”,比如笔者测试了一下,当询问“计算一下科比的BMI?”,OpenManus可以很准确的实现**谷歌搜索——浏览器访问——python计算这个过程。但如果询问“计算科比、梅西的BMI并排序?”,无论我改写了几次prompt,OpenManus都没有给我满意的回答。 此外,无论是在工具参数信息、还是prompt、memory管理中,都可以看到agent应用大模型token消耗量巨大,即使我们不考虑token成本,但大模型的上下文仍然是有限的,这种资源消耗也会直接导致模型在处理多步骤任务时面临信息截断的风险 —— 早期的关键信息可能因上下文溢出而被丢弃,进而引发推理链条的断裂。更值得警惕的是,当模型试图在有限的上下文中 “脑补” 缺失的信息时,往往会产生与事实不符的幻觉。 鉴于此,尽管 OpenManus 展示出了利用工具链解决复杂问题的潜力,不过距离成为一个实用、高效且稳定的生产级人工智能助手仍有很长的路要走。未来,开发者们或许需要在优化工具使用逻辑、提升多任务处理能力、降低大模型 token 消耗以及增强上下文管理等方面进行深入探索与改进。同时,对于普通用户而言,在体验这类项目时,也应该保持理性和客观的态度,既看到其创新性和趣味性,也认识到其当前存在的局限性。希望在技术的不断迭代和完善下,OpenManus 以及类似的项目能够早日突破现有的瓶颈,真正为人们的工作和生活带来实质性的帮助。 往期回顾 1.得物技术部算法项目管理实践分享 2. 商家域稳定性建设之原理探索|得物技术 3. 得物 Android Crash 治理实践 4. 基于ANTLR4的大数据SQL编辑器解析引擎实践|得物技术 5. LSM-TREE从入门到入魔:从零开始实现一个高性能键值存储 | 得物技术 文 / 汉堡 关注得物技术,每周一、三更新技术干货 要是觉得文章对你有帮助的话,欢迎评论转发点赞~ 未经得物技术许可严禁转载,否则依法追究法律责任。

优秀的个人博客,低调大师

Fortinet Security Fabric 再进化,提供高度一致性、自动化的网络安全平台

近日,Fortinet宣布发布其作为SecurityFabric安全平台的核心-FortiOS更新为7.0版本。FortiOS 7.0 版本的更新,超过 300 多项新特性增加与增强;使SecurityFabric安全平台的能力:全面覆盖数字化攻击平面,全方面的可见性; 安全组件深度集成,共享威胁情报;及AI驱动动态协同,进一步得到强化。 基于FortiOS7.0的Security Fabric为组织提供高度融合的网络安全平台 许多关键业务的发展趋势正在推动组织加速数字化创新,企业将更多的应用迁移到云端,设备边缘与网络边缘正在出现爆炸式增长,这推动了数字世界与物理世界的深度融合。但是威胁态势也随之发生了巨大的变化。新的边缘设备、新的应用、新的生态系统带来了更多的攻击敞口,远程办公人员成为了网络攻击者的重要目标。同时,缺乏保护的分布式架构、更快的网络让攻击者具备了前所未有的攻击效率。 在此背景下,组织需要对于安全防护平台进行革新,以跟上动态变化的安全形势发展,同时还能够提供全面可视性、数据、分析、检测以及对网络攻击协调一致的及时响应。为了提供上述能力,通过Fortinet Secuirty Fabric平台的核心-FortiOS7.0的发布,基于一套操作系统的产品与解决方案集成与整合,提供了覆盖网络安全、SD-WAN、交换和无线接入、网络访问控制、身份认证、公有云和私有云安全、终端安全以及 AI 驱动型高级威胁防护解决方案,同时提供比任何其他厂商都更多的消费模式选择。 Fortinet Security Fabric集成了 FortiOS 7.0 海量的新特性,这包括零信任网络访问支持远程访问与应用控制、通过 SASE 随时随地提供一致的安全性、全新自修复SD-WAN 功能、跨多云部署优化性能和安全性等,能够实现跨整个数字化攻击面一致且灵活的安全保护,保护任何位置的人、设备和数据的安全。 实现网络安全的全面覆盖、深度结合与动态协同 Fortinet Security Fabric提供了基于统一平台的安全可见性与一致性,避免了组织由于部署分散的网络安全产品所带来的问题,并覆盖了更广阔的的数字化攻击表面和周期,提供自修复的安全网络连接。通过Fortinet Security Fabric安全平台,组织能够实现如下安全保护效果: 在任何边缘、云端、终端上保护任何应用:Fortinet Security Fabric集成了Fortinet广泛的产品线与能力,能够通过相互协调的威胁检测和策略实施来保护各种攻击平面,还能通过自适应云安全能力在混合云、跨云中保护任何应用。 实现安全、高效的网络连接与管理:Fortinet Security Fabric的安全驱动型网络把网络连接和安全性整合为可扩展至任何边缘的单一集成式系统,还能够通过零信任访问了解并控制企业网络内外的所有人和物。 简化组织的安全管理并提升效率:Security Operations Center (SOC)与Network Operations Center (NOC)是驱动整个Security Fabric的网络和安全管理中心,其具备AI驱动安全的自修复型网络运营能力,实现更智能化的网络运营,并可通过 FortiCloud 将复杂的管理操作简化为统一管理体验。 “在数字化转型的推动下,传统网络的边界已经日趋模糊,传统单点的安全解决方案更是无法有效提供集成和自动化,这让用户无法利用现有众多供应商来实现有效防御和积极的安全事件响应”,Fortinet中国区高级产品市场经理岑义涛表示,“Fortinet的使命是保护任何位置的人、设备和数据的安全,构建可信任的数字世界。我们希望通过Fortinet Security Fabric,在一套平台与架构中原生集成所有的安全能力,不论这些能力是否由Fortinet产品提供,以期在不断扩大的攻击面中快速发现并响应威胁”。 【责任编辑:贺鑫 TEL:(010)68476606】

优秀的个人博客,低调大师

Rust + Tauri 开源工具箱再进化

最近一直在持续开发自己的开源桌面工具箱 ToolForge,今天迎来了一个新的版本: ToolForge v0.2.0 正式发布! ToolForge 是一款基于 Rust + Tauri 2 构建的开源桌面工具箱,面向开发者和效率工作者,希望将日常开发、文件处理、数据转换、系统管理等常用工具整合到一个应用中。 在之前的 v0.1.10 版本中,ToolForge 正式引入了插件市场、WASM Component 运行时以及独立插件包格式 .tfp。 当时的目标很简单: 让工具不再完全依赖桌面应用的发布周期,可以像安装扩展一样,按需安装和更新。 本次 v0.2.0 继续围绕这一目标完善插件体系。 除了新增十余款在线工具,还实现了官网一键安装插件、WASM 插件网络能力增强、工具执行历史升级,以及大量开发者工具的功能扩展。 这次更新的重点不仅是工具数量,而是让 ToolForge 的插件生态真正开始运转。 🚀 一、插件市场全面升级 1. 官网一键安装插件 这是 v0.2.0 最直观的变化之一。 此前,用户需要打开 ToolForge 桌面应用,再进入插件市场寻找并安装工具。 现在,可以直接从 ToolForge 官方网站发起插件安装! 官方网站:https://toolforge.devlive.org/ 用户可以在网站上浏览工具目录,查看不同插件的功能介绍,并通过安装入口唤起桌面应用完成插件安装。 整个流程变得更加简单: 浏览官网 → 找到工具 → 点击安装 → 通过 ToolForge 安装插件。 对于第一次接触 ToolForge 的用户,也可以先通过官方网站了解工具生态,再决定安装哪些功能。 需要说明的是,一键安装依赖桌面应用和系统链接处理能力。如果没有安装 ToolForge,或者系统无法正常唤起应用,仍然需要先安装应用或检查相关配置。 2. 内置工具与在线插件正式区分 随着插件市场不断扩展,ToolForge 也开始调整原有的工具组织方式。 现在,官方网站会明确区分两类工具。 内置工具(Built-in Tools) 跟随 ToolForge 桌面应用发布,无需单独安装。 在线插件(Online Plugins) 通过插件市场按需安装,可以独立更新。 这意味着用户不需要为了使用少量工具而让应用一直集成所有功能。 同时,本次还将部分原有工具迁移为在线插件,例如: HTTP Client Timestamp Converter Date Calculator SQL Formatter SemVer Crypto 这些工具不再需要始终作为内置功能随应用一起发布,而是可以通过插件市场进行管理。 本次也完善了插件迁移过程中的自动安装逻辑,并修复了可能出现的重复安装问题。 3. 插件详情展示 现在插件市场支持查看在线插件和本地已安装插件的详细信息。 相比此前主要提供安装入口的方式,插件管理体验更加完整。 随着插件数量不断增加,插件详情也会成为用户了解工具能力的重要入口。 🧩 二、WASM 插件运行时进一步增强 v0.1.10 引入 WASM Component 运行时后,ToolForge 已经具备了安装和执行在线插件的基础能力。 但如果希望插件覆盖更多复杂场景,仅仅能够运行还不够。 例如: HTTP 客户端需要发起网络请求。 gRPC 客户端需要处理网络通信。 文件生成工具需要将结果保存到本地。 实时接口调试需要处理持续返回的数据。 这些功能都需要宿主应用向插件提供相应的能力。 因此,本次 v0.2.0 进一步扩展了 WASM 插件运行时。 1. 新增网络、回调与文件写入能力 现在,在线插件可以通过宿主提供的接口使用: 网络访问 回调能力 文件写入 HTTP 流式响应 HTTP Trailers 宿主系统时区 这些能力让在线插件可以实现更加复杂的开发者工具。 尤其是对于 HTTP、gRPC、实时接口调试等场景来说,网络和流式处理能力非常重要。 2. 支持 HTTP 流式响应 本次完善了 WASM 插件处理 HTTP 流式响应的机制。 同时,增加了等待响应头阶段取消请求的能力。 这类改进虽然不一定直接体现在界面上,但对于需要处理长连接、流式数据和网络请求的插件来说,是重要的基础设施。 从简单的数据计算,到网络请求、流式响应和文件写入,ToolForge 的在线插件正在具备更丰富的实际应用能力。 ✨ 三、新增十余款在线插件 本次 v0.2.0 新增了多款在线插件,覆盖 API 调试、数据库分析、前端开发、安全检查、数据处理和日常效率等场景。 1. gRPC 客户端 新增 gRPC Client 在线插件。 对于经常开发微服务和后端接口的开发者来说,除了 HTTP REST API,gRPC 也是常见的通信方式。 现在 ToolForge 的在线插件生态开始覆盖 gRPC 客户端场景,让开发者能够在统一的桌面工具平台中处理更多类型的接口调试任务。 2. WebAssembly 模块检查器 新增 WASM Inspector。 随着 WebAssembly 在浏览器、服务端和插件系统中的应用不断增加,查看和分析 WASM 模块也逐渐成为一类实际需求。 WASM Inspector 主要用于检查 WebAssembly 模块信息。 对于正在学习 WebAssembly,或者开发 WASM 相关应用的开发者来说,是一个很有针对性的工具。 3. PostgreSQL 执行计划分析器 新增 PG Plan Analyzer。 PostgreSQL 的 EXPLAIN 可以帮助开发者了解 SQL 查询执行过程。 但当执行计划比较复杂时,直接阅读 JSON 格式的执行计划并不方便。 新增的工具可以分析 PostgreSQL 的 EXPLAIN JSON 数据,帮助开发者检查查询执行计划。 对于 SQL 性能分析和数据库优化场景会比较实用。 4. CSP 安全策略检查器 新增 CSP Inspector。 CSP(Content Security Policy)是 Web 应用中常见的内容安全策略机制。 开发者可以通过 CSP 限制页面允许加载的脚本、样式等资源来源。 但复杂的 CSP 配置往往不容易阅读。 这个工具可以离线检查 CSP 配置,辅助开发者理解和分析相关安全策略。 5. Source Map 堆栈还原 新增 Source Map Symbolicator。 前端项目打包之后,JavaScript 代码通常经过压缩和转换。 当生产环境出现错误时,堆栈中的位置可能对应打包后的代码,而不是原始源码。 这个工具可以利用 Source Map 对堆栈信息进行符号还原,辅助开发者定位错误。 对于前端线上问题排查具有实际价值。 6. EditorConfig 规则检查器 新增 EditorConfig Inspector。 很多项目通过 .editorconfig 统一代码格式,例如缩进方式、字符编码和换行规则。 但当项目包含多个配置文件或者复杂的匹配规则时,开发者可能不清楚某个文件最终应用了哪些配置。 这个工具可以解释实际生效的 EditorConfig 规则,方便检查项目配置。 7. Gitignore 模板生成器 新增 Gitignore Generator。 开发新项目时,经常需要根据技术栈配置 .gitignore。 例如 Rust、Java、Node.js 或其他开发环境。 现在可以通过离线模板生成器创建对应的忽略规则,减少重复查找和手动编写的工作。 8. LCOV 覆盖率查看器 新增 LCOV Viewer。 LCOV 是一种常见的代码覆盖率数据格式。 对于需要查看测试覆盖率的开发者,可以通过该工具离线浏览 LCOV 覆盖率数据。 适用于测试分析、CI 结果检查以及代码质量评估等场景。 9. 国际化翻译文件对比 新增 i18n Diff。 这是一个对开源项目维护者很有帮助的工具。 当项目支持多种语言时,经常会出现某些语言文件缺少翻译键的问题。 例如: 中文语言文件增加了一个新的配置项,但英文或日文没有同步更新。 新增的 i18n Diff 可以比较翻译文件中的 Key,帮助发现不同语言之间的键名差异。 对于维护多语言项目的开发者来说,可以减少人工检查的工作量。 10. User-Agent 解析工具 新增 User-Agent Parser。 支持离线解析 User-Agent,并解释解析结果。 在后端开发、日志分析和浏览器兼容性排查时,经常需要分析请求中的 User-Agent 信息。 通过这个工具,可以更加方便地了解 User-Agent 字符串所表达的信息。 11. 测试银行卡生成与校验 新增 Test Card 在线插件。 主要面向开发测试场景,支持生成和校验测试卡号。 本次还增加了: 中国银行卡相关测试数据 指定数字范围 银行卡样式展示 对于支付系统开发、表单校验和测试数据准备等场景,可以减少手动构造数据的工作。 需要注意,生成的测试数据不代表真实可用的银行卡,也不能代替支付服务商提供的官方测试卡及沙箱环境。 12. 快速绘图工具 新增 Quick Plot。 用于快速绘制数据图表,为 ToolForge 的数据处理工具生态增加了一项可视化能力。 在日常开发和数据分析过程中,有时只需要快速查看一组数据的变化趋势,而不需要启动完整的数据分析平台。 Quick Plot 就是面向这类轻量化场景的工具。 🔧 四、已有工具继续增强 除了新插件,本次还增强了多个已有工具。 1. HTTP Client 支持 SSE HTTP Client 新增 Server-Sent Events(SSE)流式响应支持。 SSE 在 AI 应用、实时通知和流式接口中非常常见。 例如,很多 AI 模型接口会通过 SSE 逐步返回生成内容。 现在 HTTP Client 可以处理这类流式响应,为相关接口调试提供支持。 2. HTTP Client 支持 OAuth 2.0 PKCE 本次还新增了 OAuth 2.0 Authorization Code with PKCE 授权方式。 对于需要 OAuth 2.0 授权的 API,可以使用授权码流程配合 PKCE 完成认证。 这对于测试第三方 OAuth 接口,以及需要用户授权的 API 场景非常实用。 3. SM2 签名调试 Crypto 在线插件新增 SM2 签名调试能力。 SM2 是中国商用密码体系中的一种公钥密码算法。 对于需要对接相关签名接口或检查签名数据的开发者,可以通过这一能力辅助排查问题。 4. ENV 文件比较与合并 环境变量编辑器新增跨环境比较与合并功能。 在实际项目中,经常存在多个环境配置文件: .env .env.development .env.production 随着项目配置不断增加,不同环境之间可能出现缺失或不一致的配置项。 现在可以比较和合并不同环境的 ENV 文件,方便统一管理配置。 5. 日期计算器增强 日期计算器新增: 农历日期 生肖 黄历相关信息 自定义节假日方案 让原本主要面向日期加减和工作日计算的工具,进一步覆盖更多日期使用场景。 6. JSON 格式化工具增强 JSON Formatter 新增常见 JSON 数据修复能力。 开发中有时会遇到格式不规范的 JSON 内容,需要先修复才能进行后续处理。 这项功能可以辅助处理常见的 JSON 格式问题,减少手动修改成本。 7. SQL Formatter 扩展数据库方言 SQL Formatter 新增以下数据库方言支持: MySQL SQLite Oracle BigQuery 让 SQL 格式化工具能够适配更多数据库使用场景。 8. Timestamp Converter 支持自然语言日期 时间戳转换工具新增自然语言及相对日期解析。 除了传统时间戳和日期格式转换,还可以处理更自然的日期表达方式。 同时,本次 WASM 运行时也增加了将宿主系统时区传递给插件的能力,为日期时间类工具提供更准确的运行环境信息。 🕘 五、工具执行历史升级 在 v0.1.10 中,ToolForge 首次加入工具执行历史。 用户可以查看历史任务,并重新运行之前的操作。 本次 v0.2.0 进一步完善了这项功能。 1. 独立记录每一次工具调用 现在可以对每一次工具调用进行独立记录。 2. 持续保留历史记录 历史记录可以长期保留,不再受到此前临时保留方式的限制。 3. 支持分页浏览 当执行历史数量较多时,可以通过分页方式查看记录。 这对于频繁使用数据转换、编码处理和开发调试工具的用户来说,可以更方便地回顾之前执行过的操作。 🛠️ 六、修复多项稳定性问题 本次 v0.2.0 还包含多项问题修复。 macOS 键鼠统计 修复了 Input Stats 相关问题,包括: 输入法切换时可能导致应用崩溃。 Caps Lock 按键可能被重复统计。 优化 Caps Lock 系统事件处理方式。 确保 Caps Lock 每次按下只统计一次。 插件市场 修复迁移为在线插件的工具可能被重复自动安装的问题。 优化插件安装反馈,在提示信息中显示插件名称。 改进在线插件相关状态处理。 WASM 与 SDK 修复防抖调用依赖比较问题。 优化 WASM Guest 绑定生成逻辑。 针对 wasm32 目标正确生成对应接口。 网络与更新 修复回调服务器释放端口的时序问题。 修复更新安装失败后待处理更新可能丢失的问题。 构建与文档 优化并行类型检查任务数量。 完善网站预发布版本的自动部署。 更新插件目录图标。 补充在线插件安装及使用文档。 🌱 七、ToolForge 正在逐步形成自己的插件生态 回顾最近几个版本的开发过程,可以看到 ToolForge 的发展方向正在不断变化。 v0.1.7:扩展基础工具 新增文件对比、Hex 查看器、PDF、文本编码转换等工具。 v0.1.8:丰富工具类型 增加文档转换、表格转换、JSON 查询、日期计算等功能。 v0.1.9:支持后台服务 让插件不再局限于一次性执行任务,开始支持持续运行的工具。 v0.1.10:插件市场上线 新增 WASM 插件运行时、.tfp 插件包、在线安装和独立发布机制。 v0.2.0:完善在线插件生态 新增十余款在线工具,支持官网一键安装,并增强插件的网络通信、文件写入和流式处理能力。 这些变化背后,一直围绕同一个目标: 让 ToolForge 从一个不断增加内置功能的工具箱,逐渐成为一个能够持续扩展的开发者桌面工具平台。 我希望未来可以有更多开发者参与进来。 不仅仅是提交新的工具功能,也可以围绕插件生态构建更多有价值的应用。 目前插件体系仍然处于持续完善阶段,但 v0.2.0 已经向这个方向迈出了重要一步。 📦 八、项目地址与下载 项目名称: ToolForge 当前版本: v0.2.0 技术栈: Rust + Tauri 2 官方网站: https://toolforge.devlive.org/ GitHub: https://github.com/devlive-community/toolforge 版本下载: https://github.com/devlive-community/toolforge/releases 完整更新记录: https://github.com/devlive-community/toolforge/compare/v0.1.10...v0.2.0 欢迎大家下载体验! 如果之前使用过 ToolForge,可以升级到 v0.2.0,体验新的插件市场和在线工具。 对于从内置迁移到在线市场的工具,也可以通过插件市场进行管理。 ❤️ 九、最后 对于我来说,v0.2.0 不只是一个版本号的变化。 从最初开发 ToolForge,到现在逐步完善插件系统,我越来越希望它能够成为一个真正开放的开发者工具平台。 应用本身保持轻量,功能通过插件持续扩展。 用户可以根据自己的需求安装工具,而开发者也有机会独立开发和发布插件。 这也是我希望 ToolForge 长期坚持的方向。 当然,项目仍然有很多不足,插件 SDK、兼容性、工具体验和文档都还有继续完善的空间。 如果你觉得 ToolForge 对日常开发有所帮助,欢迎在 GitHub 点个 Star ⭐。 也欢迎通过 Issue 和 Pull Request 提出建议、反馈问题,或者参与插件开发。 最后想问大家一个问题: 如果可以为 ToolForge 开发一个在线插件,你最希望它解决什么问题? 欢迎在评论区交流! GitHub: https://github.com/devlive-community/toolforge 官网: https://toolforge.devlive.org/ Releases: https://github.com/devlive-community/toolforge/releases

优秀的个人博客,低调大师

企业级AI Agent工程化落地全生命周期:从需求定义到持续进化的架构实践

在企业级场景中,AI Agent的价值释放绝非“一个Prompt+一个LLM”即可实现。真正的挑战在于如何将Agent从原型玩具转化为生产级、可治理、可迭代的数字劳动力。这需要一套覆盖需求锚定、角色塑形、认知增强、工具集成、流程编排、质量验证、安全部署及持续运营的完整工程化方法论。本文结合一线实践,系统阐述企业级AI Agent的架构设计路径,旨在为技术决策者提供可落地的参考框架。

优秀的个人博客,低调大师

Jeecg-AI 应用平台 v3.9.1 重磅发布:从对话到智能体,企业级 AI 开发全面进化

写在前面:为什么企业需要一个 AI 应用平台? 当我们谈论 AI 落地时,真正的挑战往往不在于模型本身,而在于如何将 AI 能力与业务系统无缝融合。市面上的 Dify、FastGPT 等平台解决了 "构建 AI 应用" 的问题,但企业还需要一整套低代码开发体系来承载这些能力。Jeecg-AI 应用平台恰好切中了这个痛点 ------ 它不仅仅是一个 AI 应用搭建工具,更是与 JeecgBoot 低代码平台深度融合的全栈式 AI 开发解决方案。 随着 v3.9.1 版本的发布,Jeecg-AI 迎来了一次里程碑式的升级。本文将从核心架构升级、智能体能力、流程编排、多模态支持、Chat2BI 等多个维度,全面解读这次重大更新。 核心引擎全面升级:LangChain4j 1.9.1 + 多模型支持 本次版本最底层的变化是将 LangChain4j 升级至1.9.1,这不仅仅是一个版本号的跳跃,而是带来了一系列关键能力的提升: 推理模型支持:平台现在原生支持推理模型(深度思考模式),且默认不开启,避免不必要的 token 消耗。开发者可以在需要复杂推理的场景下按需启用。 流式调用接口:新增流式调用能力,用户在对话时可以实时看到 AI 的输出过程,体验从 "等待结果" 升级为 "实时交互"。 多会话模式:支持同时维护多个独立会话,适用于客服、多角色对话等复杂业务场景。 文件解析能力:AI 聊天支持上传文件并自动解析内容,让对话不再局限于纯文本。 在大模型支持方面,v3.9.1 进一步扩展了模型生态: 新增Claude模型接入 新增VL(视觉语言)模型支持 新增千帆大模型接入 通义千问深度集成:支持参数调整和联网搜索 MCP 协议支持 HTTP 和 STDIO 两种命令类型,为工具调用提供更灵活的选择 AI 应用升级为智能体:不只是对话,更是自主决策 这次版本中一个标志性的变化是:AI 应用正式升级为智能体(Agent)。这意味着 AI 应用不再只是简单的 "问答机器人",而是具备了记忆、变量管理、插件调用、流程协作和 MCP 工具使用等完整的智能体能力。 具体来说,智能体现在支持: 记忆系统:跨对话保持上下文记忆,AI 可以 "记住" 之前交流的关键信息 变量管理:在对话流程中定义和传递变量,实现更复杂的业务逻辑 插件机制:通过插件扩展智能体的能力边界 流程编排:智能体可以直接调用 AI 流程,将复杂任务分解执行 MCP 工具:通过 MCP 协议接入外部工具和服务 AI 绘画:智能体内置绘画能力,支持文生图、图生图等多模态交互 卡片式内容回复:支持富文本卡片内容展示,不再局限于纯文字回复 同时,平台还新增了AI 应用门户和提示词管理功能。应用门户为企业提供了一个统一的 AI 应用入口,用户可以在门户中浏览和使用各类 AI 应用;提示词管理则让 AI 应用的 Prompt 可以被系统化地管理和复用。 AI 流程编排:可视化设计,可观测执行 AI 流程编排能力是 Jeecg-AI 区别于其他 AI 平台的核心竞争力之一。v3.9.1 在流程编排方面新增了多种实用节点: 变量提取节点 & 变量聚合节点:在流程中灵活地提取和合并变量数据 n8n 循环节点:支持循环处理逻辑,批量执行任务 定时触发器:按时间计划自动触发流程执行 SQL 节点:直接在流程中执行 SQL 查询,打通数据库访问 知识库写入节点:流程执行结果可直接写入知识库,实现知识的自动积累 此外,流程还支持复制功能(快速基于现有流程创建新版本),以及被应用直接调用的能力,让流程真正成为可复用的业务组件。 Chat2BI:用自然语言生成数据图表 v3.9.1 推出了全新的Chat2BI功能,这可能是企业用户最期待的功能之一。通过自然语言对话,用户可以直接生成各类数据图表,无需编写 SQL 或配置报表。 Chat2BI 支持以下能力: 丰富的图表类型:柱状图、折线图、饼图、多列柱状图、多行折线图、折柱图、面积图、雷达图、仪表盘 多数据源查询:系统中配置的所有数据源都可以通过对话进行查询,未指定数据源时默认使用系统数据库 自然语言查询:用户只需描述查询需求,AI 自动解析并生成相应图表 已知数据生成图表:直接输入数据即可生成可视化图表 试想一下,业务人员不需要找开发写报表,只需说一句 "帮我看看上个月各部门的销售额对比",系统就自动查询数据并生成柱状图。这对于降低数据分析门槛有着巨大的实际价值。 AI 多模态能力:从文本到图像的跨越 本次升级中,多模态能力的引入让 Jeecg-AI 的应用场景大幅拓展: AI 图片模型:支持千问和 OpenAPI 的图片模型 文生图(Text-to-Image):通过文字描述生成图片 图生图(Image-to-Image):基于参考图片进行风格迁移或编辑 AI 海报生成:一键生成营销海报 这些能力特别适合电商、营销、内容创作等需要频繁制作视觉素材的业务场景。结合智能体的卡片式内容回复,用户可以在对话中直接获取生成的图片。 AI 工具箱:覆盖日常办公高频场景 v3.9.1 新增的 AI 工具箱提供了一组开箱即用的 AI 工具,覆盖日常办公高频场景: AI 简历生成:自动生成 Word 格式的专业简历 AI 商品搜索助手:智能搜索和推荐商品 AI 绘画 & AI 海报:快速生成视觉素材 AI 写作:辅助内容创作 OCR 识别:图片文字提取 同时,平台还提供了多个应用场景案例 ------ 看图说话、商品搜索回复、帮我写作、图片识别等 ------ 可以直接使用或作为自定义智能体的参考模板。 知识库系统:企业知识的智能管理 Jeecg-AI 的知识库系统基于 RAG(检索增强生成)架构,支持从 PDF、PPT、Word 等多种文档中提取文本并构建知识库。一个值得关注的特色是:支持直接导入包含图片的 Markdown 文档库,这在同类产品中并不常见。 相比 Dify 等平台,Jeecg-AI 在知识库方面的差异化优势在于:对话回复格式保留原样、PDF 格式保持效果更好、与业务系统集成更便捷。 Online 功能同步增强 随着 AI 能力的升级,Online 低代码模块也同步进行了多项改进: 表单列表列宽支持拖动调整,并新增默认列宽设置(Issue #9123) 表单和列表支持字典颜色显示,数据展示更直观 优化 AI 账号配置校验:未配置或配置错误时,Online 生成测试数据的提示信息更加友好 自定义按钮排序功能修正,支持清空排序设置 修复 Online 报表查询异常(Issue #9213) 修复 Online 报表左联 SQL 在 SQL Server 环境下的兼容性问题(Issue #9220) 修复编辑时 long 类型字段未赋值导致的报错 修复 loaded 方法隐藏字段导致只读字段变可写的问题(Issue #9223) 修复一对一子表编辑后详情页不更新的问题 SysDataSourceController 的 queryOptions 接口添加权限检查(Issue #9288) 这些改进看似细微,却直接影响着开发者的日常使用体验。特别是列宽拖动调整和字典颜色显示这两个功能,解决了社区反馈已久的痛点。 第三方系统集成:一键嵌入 AI 能力 Jeecg-AI 支持通过iframe 嵌入的方式将 AI 聊天助手快速集成到第三方系统中。这意味着企业现有的业务系统无需大规模改造,只需嵌入一段代码,就能为用户提供 AI 对话能力。 快速上手 如果你想立即体验 Jeecg-AI 的能力,可以通过以下方式快速开始: 在线演示:http://boot3.jeecg.com(默认账号:admin / 123456) 源码地址:https://github.com/jeecgboot/jeecg-ai 技术文档:https://help.jeecg.com/aigc 视频教程:https://www.bilibili.com/video/BV1zmd7YFE4w 项目支持 IDEA 启动和 Docker 一键部署两种方式,后端基于 Spring Boot 3.5.5 + LangChain4j,前端基于 Vue 3 + TypeScript + Vite 6 + Ant Design Vue 4。 总结与展望 Jeecg-AI v3.9.1 的发布标志着平台从 "AI 对话工具" 向 "企业级 AI 智能体平台" 的关键跨越。智能体升级、流程编排增强、Chat2BI、多模态能力、AI 工具箱等新功能的加入,让企业可以更低成本、更高效率地构建和部署 AI 应用。 从技术趋势来看,AI 与低代码的融合正在成为企业数字化转型的主流路径。Jeecg-AI 通过将 AI 能力深度嵌入低代码开发体系,为开发者提供了一条从 "原型到生产" 的快捷通道。期待下一个版本带来更多惊喜。

资源下载

更多资源
Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册