Day181920:大模型基本概述+API调用
大模型前置话题
什么时候听说大模型的?
在大家的记忆中是从什么时候开始听说或者了解大模型的?相信大部分人应该是在22年底和23年期间。但是大家知道吗,其实早在2020年6月份的时候,当时OpenAI推出了1750多亿参数的GPT-3的时候,国外就有很多创业形的科技公司就开始围绕gpt3大模型进行了商业转型和应用,到今天都已经成为了市值几十亿美元的大型科技公司。
那在2025年的今天,国内有多少企业是在真正应用大模型创业呢?大模型的技术红利不应该只被老美独享吧!因此,大模型技术在国内的推广和普及就变的至关重要。衷心的希望日后会有更多人入局大模型,更多人可以共享大模型的技术红利。
大模型不能只被老美独享
我们都知道美国的经济很糟糕,甚至是水深火热、民不聊生。虽然老美自身存在很多很严重的问题,但是不得不说老美在人工智能上的创新发展的眼光和能力还是很强的。美国的投资界把人工智能这次的大模型技术看成是1980年代的PC和1995年的互联网。所以他们就觉得大模型就是一场工业革命级别的一个机会,他们也有一个观点,那就是一旦他们美国在人工智能大模型上形成了自己的优势那对其他国家甚至对全球竞争来说,那就是降维打击。
因此我们特别希望我们国家无论是上层的政府官员还是中层的企业家还是下层的创业者、技术人员甚至是普通大众都能够特别的意识到大模型绝对是我们这一代人今天能够碰到的最大的一次机会。就像360创始人周鸿祎所说的:大模型就是一场工业革命级别的一次机会,工业革命意味着什么?意味着所有的行业都将会重新洗牌。并且这场工业革命,不仅是人类有史以来最大的一场工业革命,也可能是速度最快的一场工业革命。
AI-First意识搭建
因此,作为普通的技术人员或者其他岗位的从业人员,我们应该如何能够快速的入局大模型呢?首先,大家要具有一定的AI信仰和AI-First的意识。所谓的AI信仰指的是,你一定要believe something,你要相信大模型是可以帮你实现各种各样的需求和功能的。
其实在前几年大模型刚出现的时候,大模型本身的能力是可以被大众所接受的,但是如何让大模型技术落地、合理的应用在不同的行业中,却不是一个简单的事情。那时,有人戏称大模型就是“拿着锤子找钉子”(对各种行业进行大模型落地方案的找寻和探索)。随着大模型在近几年的急速发展,在国外大模型的落地方案也变的越来越多。此时,此时国内的各大厂商就都开始急切的找“钉子”(落地方案)了,因为谁先找到这颗“钉子”,谁就能在大模型行业落地上撕开一个口子。
因此,大家需要记住:随着大模型技术的不断发展,在各行各业大模型都会有无限的可能!
4.究竟什么是大模型
说了这么多大模型重要的因素,那么究竟什么是大模型?我们如何通俗的理解大模型这项伟大的AI技术呢?
我们可以把大模型类比生活场景中的各种“模具”:我们在生活中会使用到很多模具,比如制作雪糕的模具、蛋糕模具、爱心煎蛋的心形模具等等。我们是可以使用这些模具来更加简单便捷且快速地完成最终要制作的成品。
如果将其映射到数学上,就像是我们听到过的数学建模:比如,一位老师想计算班级100位同学的期末总成绩,那么根据学校本学期的要求,考试成绩占总成绩的70%,平成成绩占总成绩的30%,那么老师们只需要找到其中的运算规律就可以指定一个通用的模型来快速计算每一个学生的总成绩:总成绩y = (考试成绩x1 * 0.7) + (平时成绩x2 * 0.3),其中该方程式就是模型的算法,而0.7和0.3这个权重占比就是模型的参数。
大模型:LLM(Large Language Model)是指具有大量参数和复杂结构的机器学习模型。这些模型可以应用于处理大规模的数据和复杂的问题。“大模型”中的“大”是指模型的参数量非常大(百亿千亿级别)。相对来讲,参数量越大,则大模型的综合能力就越强。
大模型的两大分支
在线大模型
大模型本身是部署在云端,用户可以通过网络调用云端大模型相关的接口进行在线使用大模型相关的功能。
因此,在线大模型具备如下优势:在线模型普遍性能更强、使用的技术门槛和硬件门槛更低、配套模型生态和服务更加完善;
但是其弊端也同时存在:首先是数据安全问题,因为使用线上大模型必须通过网络进行数据传输,需要将本都数据传输给在线大模型,才可以基于大模型本身的能力对数据进行分析、处理和其他操作。但是一旦企业生产资料联网,就肯呢个会带来数据安全隐患,无法保障内容真实可信等诸多痛点的发生。还有就是,在线大模型的企业应用会产生长期的费用,在线大模型会根据调用次数或者按量进行计费,如果一旦使用频率和规避较大,则会产生较高的费用。最后一点就是在线大模型无法很好的定制化,也就是无法从训练语料进行定制化训练。
开源大模型
开源大模型是可以在本地设备上进行部署和使用的。相比与在线大模型,开源大模型可以使⽤更多微调框架进⾏模型微调,微调空间更⼤,更有可能快速完成定制化⼤模型训练;此外,数据可以直接本地训练模型,⽆需在线提交数据进⾏在线模型微调,数据安全也将更有保障;
但是,一般大模型的参数量级都会比较大,动不动就是几十亿、几百亿、几千亿的量级。因此本地部署,需要提供较高配置的硬件设备,该设备相对费用也不会太低。好在这是一次投资即可终身使用。
大模型的应用
随着人工智能技术的不断发展,AI大模型已经成为垂直行业应用的热点。
然而,AI大模型虽然功能强大,但在垂直行业应用中存在一些突出的问题,如缺乏特定行业领域的专有知识,尤其是深度知识、私有知识、保密知识等;还有就是输出内容很难精确控制;常常会出现幻觉(一本正经地胡说八道)等问题。
为解决这些问题,有三种在垂直行业中应用AI大模型的方法,包括重新训练、微调和知识库检索。
利用行业知识重新训练AI大模型
由于通用AI大模型缺乏行业专有知识,重新训练AI大模型成为一种可行的解决方案。
该方法的基本思想是,将行业相关的数据集和专业知识用于重新训练AI大模型,使其拥有行业特定的理解和知识。这样,AI大模型在垂直行业中的应用就能更好地理解和处理相关的任务和问题。
例如,在医疗领域中应用AI大模型时,可以利用医学文献、诊断报告和临床数据等专业知识进行模型的重新训练,使其具备医学背景和专业判断能力。
因此,重新训练大模型可以提高AI模型在特定领域中的准确性和专业性,并降低产生幻觉的可能性。不过,重新训练需要大量的数据,且对算力要求较高,对人力资源、算力费用和时间成本要求都非常高。
利用行业知识对AI大模型进行微调
除了重新训练,微调是另一种常用的方法来应用AI大模型于垂直行业。
微调是指在通用AI大模型的基础上,通过在特定的行业数据集上进行再次训练,调整模型的部分参数,以适应特定行业的需求。这种方法相比于重新训练,既可以保留通用AI大模型的原生能力,又能增加对行业问题的理解能力。例如,在金融领域中,可以利用金融数据和交易信息微调模型,以实现更准确和适应特定金融市场应用场景的预测和建议。
微调是在通用AI大模型的基础上,通过针对特定行业场景进行精细调整来实现更好的适应性。微调相对于重新训练而言,时间和资源消耗较少。
利用行业知识建立知识库
当AI大模型无法提供准确答案或输出时,可以利用行业知识建立知识库模型,充分融合AI大模型的通用知识和知识库的专有知识,使得大模型可以提供更有针对性的输出。
例如,在法律咨询领域,当AI大模型遇到具体法律案例时,可以将相关法律条款和判例作为知识库模型的输出,促进AI大模型产生更准确的法律意见或建议。
通过建立行业知识库和企业私有知识库模型,不仅可以提高输出内容的准确性,而且可以大大降低幻觉问题影响。但知识库模型的效果与知识库的质量和覆盖度密切相关。此外,不断更新、维护和扩充知识库也是一项重要的任务。
1、Reasoning 大模型
1.1 基本概述
Reasoning大模型特指 ”推理大模型“(Reasoning Large Language Model)是专门设计用于处理需要复杂推理任务的大型语言模型。
1.2 核心概念
推理特指的是什么呢?如何理解模型的推理能力呢?
- 推理能力的定义:推理是指根据已知的信息和知识,通过逻辑推导得出新的结论或答案的过程。对于大模型而言,推理能力使其能够处理不仅仅是简单的事实查询,还包括解决复杂的问题、进行逻辑推断、数学计算、理解代码等需要多步思考和分析的任务。
- 与常规大模型的区别:常规的大模型主要侧重于对大量文本数据的学习和理解,以便生成流畅、自然的文本回应,但它们通常直接输出最终的答案,而不展示中间的推理过程。而推理大模型在回答问题前,会先将问题拆解为更小的步骤,即推理步骤或思维链(Chain of Thought, CoT),然后将这些推理过程和最终答案一起输出,使人们能够看到模型的思考过程和逻辑推导路径。
1.3 技术实现
要使得模型具备强大的推理能力,可以从如下3点(架构基础、训练方法和提示工程)进行技术实现:
-
架构基础
-
推理大模型通常基于Transformer架构构建,这种架构能够有效地处理长序列数据,并且在自注意力机制的帮助下,可以捕捉到输入数据中的复杂依赖关系,为推理提供了良好的基础。
自注意力机制(Self-Attention Mechanism)是Transformer架构中的一个核心部分。简单来说,自注意力机制就像是给模型装上了一双“慧眼”,让它能够同时关注输入数据中的所有部分,并自动判断哪些部分更加重要。这样,模型就能更好地理解数据的整体结构和内在联系。想象一下你在阅读一篇文章。当你读到文章中的一个词时,你的大脑会不自觉地回忆起与这个词相关的其他词或句子,帮助你更好地理解当前的内容。这就是一种注意力机制。 在推理大模型中,自注意力机制的工作方式类似。当模型处理一个句子时,它会检查句子中的每个词,并通过比较这些词之间的关系来确定它们的重要性。例如,在处理句子“我喜欢在公园里散步”时,模型会发现“我”和“喜欢”之间有很强的关联,因为“我”是动作的执行者;同样,“散步”和“公园”之间也有紧密的联系,因为“散步”通常发生在“公园”里。通过这种方式,模型能够捕捉到句子中的复杂依赖关系,从而更准确地理解其含义。 因此,自注意力机制使得推理大模型能够更有效地处理长序列数据,并在自然语言处理、语音识别等领域展现出强大的性能。
-
-
训练方法
推理模型的训练需要基于(预训练、微调和强化学习)来进行,以确保模型具备强大的推理能力-
预训练:模型首先在大规模的无标注文本数据上进行预训练,学习语言的基本结构和模式,获得广泛的语言知识和世界知识。这一阶段的数据量通常非常大,以涵盖尽可能多的语言现象和信息。
-
微调:在预训练的基础上,使用特定领域或有标注的数据对模型进行微调,以优化其在特定任务上的性能和输出风格。例如,对于推理任务,可能会使用包含推理链的数据集进行微调,让模型学习如何生成合理的推理步骤。
-
强化学习:部分推理大模型还会采用强化学习技术,通过奖励模型来评估模型输出的质量和准确性,并根据奖励信号不断调整模型的参数,以提高模型的推理能力。
想象一下,一个孩子(模型)刚开始学习解决问题时,他可能会尝试不同的方法(动作),而每次尝试后,他会根据结果得到一些反馈(奖励信号)。如果某种方法得到了好结果(比如解决了问题或者得到了表扬),那么孩子就更有可能在下次遇到类似问题时再次使用这种方法。这就是强化学习的基本思想:通过“试错”和“延迟回报”来不断学习和改进。
-
-
提示工程
- 提示工程是提高推理大模型性能的重要手段之一。通过精心设计输入提示,引导模型按照预期的方式生成推理步骤和答案。例如,在提示中明确要求模型“一步步思考”“详细解释推理过程”等,可以帮助模型生成更符合要求的回答。
1.4 应用场景
-
学术研究:帮助研究人员解决复杂的学术问题,如数学证明、科学理论推导等,提供新的研究思路和方法。
-
教育领域:辅助学生学习,解答学科相关的问题,提供详细的解题步骤和解释,培养学生的逻辑思维和解决问题的能力。
-
商业决策:为企业提供数据分析、市场预测、风险评估等方面的支持,帮助企业做出更明智的决策。
-
智能客服:更准确地回答用户的问题,提供更详细、专业的解决方案,提高客户服务的质量和效率。
1.5 总结
总的来说,推理大模型通过独特的技术实现和广泛的应用场景,展现出了强大的能力和潜力。随着技术的不断进步和应用需求的不断提高,推理大模型将在未来发挥更加重要的作用。
2、deepseek理论篇
2.1 基本概述
深度求索(DeepSeek)是一家专注于通用人工智能(AGI)研发的中国科技公司,其推出的DeepSeek大模型是公司核心技术成果之一。目前deepseek支持智能对话、文本生成、语义理解与计算推理、代码生成补全等多种复杂任务,还支持图像、音频等多模态输入。
在技术架构上deepseek采用了混合专家(MoE)架构,通过动态路由机制,仅激活部分参数进行计算,有效降低计算能耗,提高特定任务的处理精度(英伟达市值蒸发)。并且,deepseek拥有庞大的参数量,如DeepSeek-V3的6710亿(671B)参数,能够理解和生成更复杂的语言,处理更多的上下文和细节信息。
一、混合专家(MoE)架构:智慧分工,高效协作
简单来讲,一个复杂的任务被分解成多个小任务,每个小任务都由最擅长它的“专家”来处理,这样不仅能提高效率,还能确保每个细节都得到精准的处理。DeepSeek大模型采用的正是这样一种高效的策略——混合专家(MoE)架构。
在MoE架构中,有多个“专家”模型,它们各自擅长处理不同类型的信息或特征。当输入数据进入模型时,一个名为“路由器”或“门控网络”的部分会智能地决定将哪些数据分配给哪些专家去处理。这样一来,每个专家都能专注于自己最擅长的领域,从而整体提高了处理效率和精度。
比如,在处理一个包含图像和文本的多模态任务时,MoE架构可以自动将图像部分交给擅长图像处理的专家,将文本部分交给擅长文本处理的专家,两者并行处理,最后再将结果合并,大大提升了处理速度和准确性。
二、动态路由机制:灵活调度,优化资源
在MoE架构中,动态路由机制起着至关重要的作用。它就像是一个智能调度员,根据输入数据的特性和当前专家的负载情况,动态地决定数据的去向。
这种动态调度不仅提高了模型的灵活性,还使得计算资源得到了更有效的利用。因为并非所有数据都需要经过所有专家的处理,只有最相关的专家才会被激活,从而大大降低了计算成本
因此,deepseek训练成本相对较低,且支持本地部署,对比同类型的大模型如GPT其硬件要求可降低60%以上!
与传统的大模型相比,DeepSeek大模型在训练成本上具有显著的优势。这得益于其MoE架构和一系列优化措施,使得模型能够在较低的硬件要求下进行高效的训练。
DeepSeek大模型支持本地部署,这意味着用户无需购买昂贵的云服务或高性能硬件设备,就能在普通的计算设备上运行和训练模型。这对于中小企业和个人开发者来说,无疑是一个巨大的福音。他们可以用更低的成本享受到先进的AI技术带来的便利和效益。
综上所述,DeepSeek大模型凭借其独特的混合专家(MoE)架构和动态路由机制,实现了高效的计算和精确的处理。同时,其在训练成本上的优势也使得更多用户能够享受到先进的AI技术带来的便利和效益。随着技术的不断进步和应用场景的拓展,DeepSeek大模型将在未来发挥更加重要的作用。
2.2 版本分支
DeepSeek的R系列和V系列是该模型体系中的两个不同分支,它们各自具有独特的特点和应用场景。以下是对这两个系列的详细对比:
一、技术架构与模型特性
-
DeepSeek-R系列
-
架构特点:R系列模型采用了先进的混合专家(MoE)架构,这种架构通过动态路由机制,仅激活部分参数进行计算,有效降低了计算能耗,提高了特定任务的处理精度。同时,R系列还引入了强化学习等先进技术,进一步提升了模型的推理能力。
我们可以将“强化学习”类比为一个“智慧成长”的过程。 想象一下,一个孩子(模型)刚开始学习解决问题时,他可能会尝试不同的方法(动作),而每次尝试后,他会根据结果得到一些反馈(奖励信号)。如果某种方法得到了好结果(比如解决了问题或者得到了表扬),那么孩子就更有可能在下次遇到类似问题时再次使用这种方法。这就是强化学习的基本思想:通过“试错”和“延迟回报”来不断学习和改进。 对于DeepSeek R系列这样的大模型来说,强化学习就像是给模型赋予了一种“自我进化”的能力。模型在面对各种复杂任务时,会像那个孩子一样尝试不同的解决方案,并根据任务的完成情况(即奖励信号)来调整自己的策略。随着时间的推移,模型会逐渐学会如何更有效地解决这些问题,从而提升其推理能力。 简单来说,强化学习就是让模型在不断的“尝试-反馈-调整”循环中变得更加聪明和高效。它帮助模型在复杂任务中找到最佳解决方案,就像那个孩子逐渐学会了如何更好地解决问题一样。所以,当DeepSeek R系列引入强化学习技术时,就意味着这个大模型拥有了更强的“智慧成长”能力,能够更好地应对各种复杂的推理任务。 -
模型性能:R系列模型在数学、代码和自然语言推理等复杂任务上表现出色,其性能可与OpenAI的o1模型相媲美。这得益于其大规模强化学习技术,使得模型能够快速掌握新知识、新技能,并适应不同的任务和场景。
-
-
DeepSeek-V系列
-
架构特点:V系列模型则更侧重于通用性和多模态处理能力。它基于标准的Transformer架构,并通过 “优化算法和增加训练数据”,逐步提升了模型的性能和适用性。V系列模型支持中英文双语处理,并能够处理包括图像、音频在内的多种模态数据。
优化算法和增加训练数据的理解: 优化算法可以让模型这个“超级大脑”运转得更高效。例如,在处理自然语言文本时,优化后的算法能够更快地理解文字之间的关系。就像原本模型需要花费较多时间和精力去理解一个复杂句子中每个词的联系,优化算法后,它能够更快地捕捉到关键词,更好地理解句子的含义,从而提升模型的性能。 而增加训练数据意味着让模型见识更多的场景和情况。以图像识别为例,如果模型原来只训练过少量几种动物的图片,它可能只能识别这几种动物。但是当增加了大量不同动物在各种环境下的图片作为训练数据后,模型就能识别更多种类的动物,而且在这些动物处于不同姿态、不同背景等情况下也能准确识别,这就提升了模型的适用性。
-
- 模型性能:V系列模型在各项评测中均表现出色,尤其在知识类任务、长文本理解、编程和数学运算等领域接近甚至超越了国际顶尖闭源模型。这使得V系列模型在实际应用中具有广泛的适用性。
二、应用场景
- DeepSeek-R系列
- 科学研究:R系列模型凭借其在复杂任务上的卓越性能,特别适用于前沿科学研究领域。例如,在数学推理、代码生成等方面,R系列模型能够提供强大的支持,帮助科研人员解决复杂的问题。
- 商业决策:对于需要高精度和复杂推理的商业决策场景,如金融分析、市场预测等,R系列模型也能够提供有力的支持。其强大的逻辑分析和决策能力能够帮助企业做出更加明智的决策。
- DeepSeek-V系列
- 内容创作:V系列模型在文本生成、图像识别等方面具有出色的表现,因此非常适用于内容创作领域。无论是撰写文章、设计图像还是生成音频内容,V系列模型都能够提供丰富的创意和灵感。
- 智能客服:在智能客服领域,V系列模型能够准确理解用户的问题并提供准确的回答。其多模态处理能力还能够支持语音、图像等多种交互方式,提升用户体验。
三、总结
综上所述,DeepSeek的R系列和V系列各有千秋,分别在不同的应用场景中展现出了卓越的性能。R系列以其强大的推理能力和复杂任务处理能力著称,适用于科学研究和商业决策等高端场景;而V系列则以其通用性和多模态处理能力见长,更适用于内容创作和智能客服等广泛应用领域。
2.3 蒸馏模型
2.3.1 基本概述
在deepseek的R系列模型中还提供了6种基于Qwen和Llama的蒸馏版本,显著提升小模型性能。这六个蒸馏小模型是DeepSeek-R1-Distill-Qwen系列(包括1.5B、7B、14B、32B)和DeepSeek-R1-Distill-Llama系列(包括8B、70B)。
蒸馏模型是一种通过将复杂、大型模型(称为教师模型)的知识迁移到一个更小、更简单的模型(称为学生模型)中,以实现模型压缩和加速推理的技术。在DeepSeek系列中,就是将R1系列大模型作为教师模型,通过特定的蒸馏方法,把知识传递给基于Qwen和Llama系列构建的学生模型。其原理是:
通过模仿教师模型的输出,训练一个较小的学生模型,从而实现知识的传递。在训练过程中,首先利用训练数据集让教师模型生成针对输入数据的响应,这些输出结果构成了后续学生模型训练的重要参考数据。然后,学生模型以此为基础进行微调,通过优化自身的参数,使其尽可能地学习和模仿教师模型的行为模式和决策逻辑,从而实现知识从教师模型到学生模型的迁移。在此过程中,学生模型不断调整自身的内部结构和参数值,以适应从教师模型传递过来的知识和经验,逐步提升自身的性能表现
通俗理解版本:用学霸和普通学生的例子解释蒸馏模型核心内容
想象一下,在一个学校里,有一个非常聪明的学霸(我们称他为“教师模型”),他在各个学科上都有出色的表现。然后,还有一个普通的学生(我们称他为“学生模型”),他想要提高自己的成绩,但不知道从何下手。可以基于如下2步实现:
第一步:教师模型的指导
教师模型(学霸)先做了一遍模拟考试题(这相当于利用训练数据集生成响应)。
他把答案和解题思路详细地写了下来,这些答案和解题思路就像是“黄金参考资料”。
现在,普通学生(学生模型)拿到了这些“黄金参考资料”,他开始以此为基础进行学习。
第二步:学生模型的微调
- 模仿与学习:
学生模型(普通学生)开始根据教师模型(学霸)提供的“黄金参考资料”来调整自己的学习方法和策略。
他会仔细对比自己的答案和学霸的答案,找出差距,并努力缩小这个差距。
- 优化自身参数:
学生模型不断调整自己的学习计划、记忆技巧等,就像是在优化自己的内部结构和参数值一样。
他尝试不同的方法,直到找到最适合自己的学习方式。
- 逐步提升性能:
随着时间的推移,普通学生逐渐掌握了更多的知识和技巧,他的成绩也开始稳步提升。
最终,他能够独立完成考试题,并且取得了不错的成绩。
- 总结
通过这个过程,我们可以看到,普通学生(学生模型)通过模仿和学习教师模型(学霸)的行为模式和决策逻辑,实现了知识的迁移和自身性能的提升。这就像是蒸馏模型中的知识传递过程一样,学生模型不断地调整自己,以适应从教师模型那里传递过来的知识和经验,从而变得越来越优秀。
具体来说,DeepSeek的蒸馏过程是通过使用R1生成的80w个推理数据样本,对较小的基础模型(例如Qwen和Llama系列)进行微调而创建的。尽管规模变小,但这些蒸馏版本仍保留了较强的推理能力。因为它们继承了R1大模型的知识和推理模式,所以在一些推理任务上能够取得不错的成绩。
2.3.2 意义和作用
- 降低部署门槛:蒸馏后的轻量级模型能够在资源受限的设备上运行,如移动设备、边缘计算设备等,大大扩展了AI技术的应用范围。
- 提升运行效率:小型模型具有更快的推理速度和更低的能耗,这对于需要实时响应的应用场景尤为重要。
- 个性化定制:蒸馏技术使得模型能够针对特定场景进行优化,满足不同应用的具体需求。
2.4 DeepSeek-R1部署方案
伴随着DeepSeek R1模型使用需求不断深化,如何才能部署更高性能的满血版DeepSeek R1模型,就成了很多应用场景下的当务之急。受限于DeepSeek R1 671B(6710亿参数)的模型规模,通常情况下部署DeepSeek R1满血版模型需要1200G-1400G左右显存(考虑百人内并发情况),也就是需要60块4090或者18块A100的显卡才能够顺利运行(总成本约在260万-320万左右)。哪怕是在半精度的情况下,实际测试下来也需要占用490G的显存,也就是需要24块4090或者7块A100才能够顺利运行(总成本约在120万至240万左右)。
在此情况下,如何以更少的成本获得尽可能好的模型性能——也就是如果进行DeepSeek R1的高性能部署,就成了重中之重。基本来说,目前的解决方案有以下2种:
第一种:采用“强推理、若训练”的硬件配置
如选择国产芯片、或者采购DeepSeek一体机、甚至是选择MacMini集群等,都是不错的选择。这些硬件模型训练性能较弱,但推理能力强悍,对于一些不需要进行模型训练和微调、只需要推理(也就是对话)的场景来说,是个非常不错的选择。
例如,45万左右成本,就能购买能运行DeepSeek R1满血版模型的Mac Mini集群,相比购买英伟达显卡,能够节省很大一部分成本。但劣势在于Mac M系列芯片并不适合进行模型训练和微调。
第二种:采用DeepSeek R1 Distill蒸馏模型
DeepSeek R蒸馏模型组同样推理性能不俗,且蒸馏模型尺寸在1.5B到70B之间,可以适配于任何硬件环境和各类不同的使用需求。其中各蒸馏模型、各量化版本、各不同使用场景(如模型推理、模型高效微调和全量微调)下模型所需最低配置如下:
FP16、INT8和INT4是指大模型硬件配置中三种不同的数值精度表示方式。
- 如果对模型精度要求极高,如医疗影像分析、高精度自然语言处理任务等,应首先考虑FP16或INT8。
- 如果需要高推理速度,如实时语音识别、视频处理等任务,可以考虑使用INT8或INT4。
- 如果存储资源是首要考虑因素,如在移动设备或嵌入式系统中部署模型,INT8和INT4可能是更好的选择。
GPT-4 发布于 2023 年 3 月 14 日,而 o1-mini 是在 2024 年 9 月 12 日发布的。
- 如果你需要处理复杂的文本生成和对话任务,GPT-4 可能是一个更好的选择。
- 而如果你需要在资源有限的环境中进行快速推理,并且对计算资源消耗有严格要求,那么 o1-mini 可能更适合你。
-
Deepseek-R1-Distill-Qwen-1.5B:
- 性能指数:2颗星,推理能力达到GPT-4o级别(int4 32位 int8 64)
- 适用场景:移动端应用或者个人助理
-
Deepseek-R1-Distill-Qwen-7B
- 性能指数:3颗星,推理能力达到o1-mini的70%左右
- 适用场景:高校实验室或者小型团队适用
-
Deepseek-R1-Distill-Qwen-14B
- 性能指数:4颗星,推理能力达到o1-mini的80%左右
- 适用场景:适用于一般商业场景
-
Deepseek-R1-Distill-Qwen-32B
- 性能指数:5颗星,推理能力达到o1-mini性能级别
- 适用场景:适用于高性能要求的商业场景
-
Deepseek-R1-Distill-Llama-8B
- 性能指数:3颗星,推理能力达到o1-mini的70%左右
- 适用场景:高校实验室或者小型团队适用
-
Deepseek-R1-Distill-Llama-70B
- 性能指数:5颗星,推理能力达到o1-mini的性能级别
- 适用场景:适用于高性能要求的商业场景
3、Deepseek-R1的API调用指南
3.1 快速开始
DeepSeek-R1正式版已于2025年1月20号正式上线,其强大的模型推理能力可以让DeepSeek-R1在数学、代码、自然语言推理等任务上取得很好的结果,性能比肩 OpenAI o1 正式版。
DeepSeek-R1的API调用也是非常简单的,但是在调用API之前需要我们完成API Key的申请:
-
访问DeepSeek官网:https://www.deepseek.com/,进入到API开放平台中
-
进行API Key的申请:
- 新用户注册即赠送10元额度,约500万token额度。
- 价格方面,DeepSeek R1价格约为OpenAI o1正式版模型的1/50:
-
注意:
-
目前DeepSeek R1模型调用不限速
-
API调用风格和OpenAI完全一致,但是暂不支持多模态和Function calling功能。
-
3.2 API调用规范
在Deepseek官网中有如下内容:
OpenAI安装:
pip install openai
调用实例:
from openai import OpenAI
ds_api_key = "YOUR_DS_API_KEY"
# 实例化客户端
client = OpenAI(api_key=ds_api_key,
base_url="https://api.deepseek.com")
# 调用 deepseek-r1 模型
response = client.chat.completions.create(
#model="deepseek-chat" 调用Deepseek-V3模型,不存在推理过程
#model="deepseek-coder" 调用的是DeepSeek的Coder模型,不存在推理过程。这个模型是专为代码相关任务而训练的,具有较强的代码生成、理解、修改和调试能力,适用于编程问答、代码补全、代码错误检测与修复等场景
model="deepseek-reasoner", #调用推理模型deepseek-r1 模型标识/名称,存在推理过程
messages=[
{"role": "user", "content": "请问,9.8和9.11哪个更大?"}
]
)
# 最终回复
response.choices[0].message.content
# 思考链
response.choices[0].message.reasoning_content
注意,在上述代码中,r1模型不光可以返回模型对于用户提问的回答,还可以返回对于用户提问问题的具体推理/思考过程,该过程就是r1模型的思考链。而思考链也是r1模型和GPT的o1模型主要的一个区别。
关于返回思考链的深度思考
如果我们可以看到r1模型的思考过程的话,那么就可以根据这个思考过程的内容去创建非常多高质量的问答数据。在问答数据中,不仅会包含问题和答案,还会包含对于问题的思考过程。这也是Deepseek可以基于r1模型蒸馏了很多小尺寸模型的主要原因。
Message参数设置方法
时至今日,“多角色” 对话基本上已经成了顶尖大模型的标配。正是基于多角色对话这一基础技术架构,大模型才能非常灵活的实现各类对话需求。而实际执行多角色对话的过程中,其核心是依靠messages参数来实现的。
messages(必填)
-
messages参数是 DeepSeek模型 API 中必填的参数之一,用于定义聊天上下文,包括用户的输入、系统的指令、助手的回复等。通过messages数组,模型可以理解当前对话的背景,从而生成更加连贯的响应。根据不同的使用场景,messages包含多种类型的消息,例如system message、user message和assistant message。下面是对messages参数及其各个子类型的详细解释。content(必填):系统消息的内容,可以是字符串或数组。如果是数组,可能包含多个类型的内容(如文本、图像)。role(必填):此处角色为system,表明这是系统发出的消息。name(可选):提供系统消息发送者的名称,尤其适用于区分多个具有相同角色的参与者。
示例代码:
response = client.chat.completions.create( model="deepseek-reasoner", messages=[ {'role':'system','content':"你是一位滑稽且幽默的小品演员。"}, {"role": "user", "content": "请问,你如何理解人生呢?"} ] ) display(Markdown(response.choices[0].message.content)) response = client.chat.completions.create( model="deepseek-reasoner", messages=[ {"role": "system", "content": "你是一位大学数学系教授"}, {"role": "user", "content": "请问,你如何理解人生呢?"} ] ) display(Markdown(response.choices[0].message.content))- 还有一个非常常见的
system message的使用方法,就是借助system消息进行聊天背景信息的设定,很多时候我们可以在system消息中输入一段长文本,这段长文本将在聊天开始之前输入到系统中,而在之后的聊天中,即可让assistant围绕这个长文本进行回答,这是一种最简单的实现大语言模型围绕本地知识库进行问答的方法。
text = '张三,男,1990年10月25日出生于中国台湾省高雄市。\ 2013年毕业于北京工业大学的信息工程专业,由于在校表现良好,毕业后被中科院信息技术部破格录取。' response = client.chat.completions.create( model="deepseek-reasoner", messages=[ {"role": "system", "content": text}, #请问张三是什么星座的?请问张三毕业后去哪里了? {"role": "user", "content": '请问张三是哪一年毕业的?'} ] ) response.choices[0].message.content-
user message表示用户发给模型的消息,是对话的核心部分之一。它定义了用户的输入内容,模型根据这些内容生成响应。content(必填):用户消息的内容,通常为文本或图像链接的数组。对于支持图像输入的模型,如 DeepSeek v2.5 ,还可以传递图像。role(必填):角色为user,表示该消息来自用户。name(可选):可以为用户指定一个名称,用于区分多个具有相同角色的用户。
示例代码:
# 创建用户消息 user_message = { "role": "user", "content": "你好,请介绍下你自己。" } -
assistant message表示助手消息,是模型根据用户消息生成的响应。-
content:类型为字符串,表示助手消息的内容,这是助手对用户提问的回答或执行任务的结果等。
-
role:类型为字符串,固定为 “assistant”,表示消息的作者角色是助手。
-
name:类型为字符串,表示对话参与者的名称,一般用于区分不同身份的助手。
-
3、Deepseek-R1的API调用指南
3.1 快速开始
DeepSeek-R1正式版已于2025年1月20号正式上线,其强大的模型推理能力可以让DeepSeek-R1在数学、代码、自然语言推理等任务上取得很好的结果,性能比肩 OpenAI o1 正式版。
DeepSeek-R1的API调用也是非常简单的,但是在调用API之前需要我们完成API Key的申请:
-
访问DeepSeek官网:https://www.deepseek.com/,进入到API开放平台中
-
进行API Key的申请:
- 新用户注册即赠送10元额度,约500万token额度。
- 价格方面,DeepSeek R1价格约为OpenAI o1正式版模型的1/50:
-
注意:
-
目前DeepSeek R1模型调用不限速
-
API调用风格和OpenAI完全一致,但是暂不支持多模态和Function calling功能。
-
3.2 API调用规范
在Deepseek官网中有如下内容:
OpenAI安装:
pip install openai
调用实例:
from openai import OpenAI
ds_api_key = "YOUR_DS_API_KEY"
# 实例化客户端
client = OpenAI(api_key=ds_api_key,
base_url="https://api.deepseek.com")
# 调用 deepseek-r1 模型
response = client.chat.completions.create(
#model="deepseek-chat" 调用Deepseek-V3模型,不存在推理过程
#model="deepseek-coder" 调用的是DeepSeek的Coder模型,不存在推理过程。这个模型是专为代码相关任务而训练的,具有较强的代码生成、理解、修改和调试能力,适用于编程问答、代码补全、代码错误检测与修复等场景
model="deepseek-reasoner", #调用推理模型deepseek-r1 模型标识/名称,存在推理过程
messages=[
{"role": "user", "content": "请问,9.8和9.11哪个更大?"}
]
)
# 最终回复
response.choices[0].message.content
# 思考链
response.choices[0].message.reasoning_content
注意,在上述代码中,r1模型不光可以返回模型对于用户提问的回答,还可以返回对于用户提问问题的具体推理/思考过程,该过程就是r1模型的思考链。而思考链也是r1模型和GPT的o1模型主要的一个区别。
关于返回思考链的深度思考
如果我们可以看到r1模型的思考过程的话,那么就可以根据这个思考过程的内容去创建非常多高质量的问答数据。在问答数据中,不仅会包含问题和答案,还会包含对于问题的思考过程。这也是Deepseek可以基于r1模型蒸馏了很多小尺寸模型的主要原因。
Message参数设置方法
时至今日,“多角色” 对话基本上已经成了顶尖大模型的标配。正是基于多角色对话这一基础技术架构,大模型才能非常灵活的实现各类对话需求。而实际执行多角色对话的过程中,其核心是依靠messages参数来实现的。
messages(必填)
-
messages参数是 DeepSeek模型 API 中必填的参数之一,用于定义聊天上下文,包括用户的输入、系统的指令、助手的回复等。通过messages数组,模型可以理解当前对话的背景,从而生成更加连贯的响应。根据不同的使用场景,messages包含多种类型的消息,例如system message、user message和assistant message。下面是对messages参数及其各个子类型的详细解释。content(必填):系统消息的内容,可以是字符串或数组。如果是数组,可能包含多个类型的内容(如文本、图像)。role(必填):此处角色为system,表明这是系统发出的消息。name(可选):提供系统消息发送者的名称,尤其适用于区分多个具有相同角色的参与者。
示例代码:
response = client.chat.completions.create( model="deepseek-reasoner", messages=[ {'role':'system','content':"你是一位滑稽且幽默的小品演员。"}, {"role": "user", "content": "请问,你如何理解人生呢?"} ] ) display(Markdown(response.choices[0].message.content)) response = client.chat.completions.create( model="deepseek-reasoner", messages=[ {"role": "system", "content": "你是一位大学数学系教授"}, {"role": "user", "content": "请问,你如何理解人生呢?"} ] ) display(Markdown(response.choices[0].message.content))- 还有一个非常常见的
system message的使用方法,就是借助system消息进行聊天背景信息的设定,很多时候我们可以在system消息中输入一段长文本,这段长文本将在聊天开始之前输入到系统中,而在之后的聊天中,即可让assistant围绕这个长文本进行回答,这是一种最简单的实现大语言模型围绕本地知识库进行问答的方法。
text = '张三,男,1990年10月25日出生于中国台湾省高雄市。\ 2013年毕业于北京工业大学的信息工程专业,由于在校表现良好,毕业后被中科院信息技术部破格录取。' response = client.chat.completions.create( model="deepseek-reasoner", messages=[ {"role": "system", "content": text}, #请问张三是什么星座的?请问张三毕业后去哪里了? {"role": "user", "content": '请问张三是哪一年毕业的?'} ] ) response.choices[0].message.content-
user message表示用户发给模型的消息,是对话的核心部分之一。它定义了用户的输入内容,模型根据这些内容生成响应。content(必填):用户消息的内容,通常为文本或图像链接的数组。对于支持图像输入的模型,如 DeepSeek v2.5 ,还可以传递图像。role(必填):角色为user,表示该消息来自用户。name(可选):可以为用户指定一个名称,用于区分多个具有相同角色的用户。
示例代码:
# 创建用户消息 user_message = { "role": "user", "content": "你好,请介绍下你自己。" } -
assistant message表示助手消息,是模型根据用户消息生成的响应。-
content:类型为字符串,表示助手消息的内容,这是助手对用户提问的回答或执行任务的结果等。
-
role:类型为字符串,固定为 “assistant”,表示消息的作者角色是助手。
-
name:类型为字符串,表示对话参与者的名称,一般用于区分不同身份的助手。
-
3.3 多轮对话
3.3.1 基本原理
首先,任何一款大模型在原始状态下都不会存在和用户对话的长期记忆,也就是所谓的上下文或者多轮对话机制。但是正是由于message参数包含多种类型的消息,例如 system message、user message 和 assistant message就可以实现“多轮对话”机制,使得模型可以具备上下文或者和用户长期对话记忆的能力。
我们只需要将模型返回的assistant message消息+用户新的提问usermessage拼接到模型的messages参数中,并再次向模型进行提问,即可非常便捷的实现多轮对话。
3.3.2 封装实现
from openai import OpenAI
ds_api_key = "sk-f010301e7xxx5214d14c30cce1e"
# 实例化客户端
client = OpenAI(api_key=ds_api_key,
base_url="https://api.deepseek.com")
def multi_chat_with_model(msg): #msg表示用户提出的问题
text = '张三,男,1990年10月25日出生于中国台湾省高雄市。\
2013年毕业于北京工业大学的信息工程专业,由于在校表现良好,毕业后被中科院信息技术部破格录取。'
messages=[
{"role": "system", "content": text},
{"role": "user", "content": msg}
]
while True:
response = client.chat.completions.create(
model="deepseek-reasoner",
messages=messages
)
# 获取模型回答
answer = response.choices[0].message.content
print(f"模型回答: {answer}")
# 询问用户是否还有其他问题
user_input = input("您还有其他问题吗?(输入退出以结束对话): ")
if user_input == "退出":
break
# 记录用户回答
messages.append({"role": "assistant", "content": answer})
messages.append({"role": "user", "content": user_input})
#多轮对话测试
multi_chat_with_model('张三哪一年毕业的?')
4、Agent智能体开发
4.1 Agent简介
Agent智能体是一个由人工智能驱动的系统或程序,能够在一定的环境中自主感知、决策和执行任务。它模拟或扩展了人类或其他生物的智能行为,旨在解决复杂问题或完成特定目标。可以广泛应用与自动驾驶、智能客服、游戏NPC、金融分析、医疗诊断等多个领域。
在Agent智能体的开发过程中,有一种实现机制,可以使得开发者可以定义、管理和调用各种函数来实现复杂的任务。这些函数可以封装具体的业务逻辑、算法或外部服务调用等。这种机制就是Function Calling!因此,Function Calling是Agent智能体开发的基础。
同时,Agent智能体利用Function Calling增强能力。因为,Agent智能体通过调用外部函数或服务(即Function Calling),可以访问实时数据、执行特定算法或调用其他资源来完成其任务。这种能力使得Agent智能体能够更加灵活地适应不同的应用场景和需求。
因此,随着AI技术的不断发展,Agent智能体和Function Calling都在不断地演进和完善。两者相互促进、相互影响,共同推动了AI技术的创新和应用落地。
4.2 Function Calling简介
4.2.1 背景和定义
我们都知道大语言模型的知识储量是巨大,并且它具备非常强大的原生能力,但是有时候我们在实际使用大模型时会感受到大模型能力上的某些局限,比如大模型无法回答超过大模型知识库截止日期之后发生的相关信息和知识,并且大模型只能给出文字的建议但无法直接帮我们解决某些实际操作性的问题(如自动进行邮件收发、自动预定车票等)。因此,这些问题的存在会极大程度上限制了大模型的实际应用价值。
在这一基本背景下,Function calling功能应运而生。该功能的本质是让大模型具有调用外部函数的能力。也就是说,当大模型遇到超出自身能力范围的需求时,可以通过访问相应的外部函数寻求解决方案。这样,大模型就可以不再仅仅根据自身的知识库进行回答,还可以额外挂载一个外部函数库,然后根据用户提问进行外部函数的检索,根据实际需求调用外部函数并获取函数运行结果,再基于函数运行结果进行回答。
毫无疑问,有了外部函数库的功能加持,大模型的处理和解决问题的能力也必将再上一个台阶。
4.2.2 核心原理
在Agent中的应用:
4.3 实时气象查询Agent开发
4.3.1 项目背景
OpenWeather是一家提供全球范围内的气象数据服务的公司,该公司的服务包括实时天气信息、天气预报、历史天气数据以及各种气象相关的报告等,并且OpenWeather开放了一定使用限度内完全免费的API,即我们可以在代码环境中通过调用OpenWeather API来进行实时天气查询、天气预报等功能,这意味着开发者可以将OpenWeather的天气预报功能加入到他们自己的应用或网站中。
4.3.2 OpenWeather注册及API key获取方法
为了能够调用OpenWeather服务,和OpenAI的API使用过程类似,我们首先需要先注册OpenWeather账号,并获取OpenWeather API Key。这里需要注意的是,对于大多数在线服务的API来说,都需要通过API key来进行身份验证,尽管OpenWeather相对更加Open,有非常多的免费使用的次数,但身份验证仍然是必要的防止API被滥用的有效手段。OpenWeather API key获取流程如下:
-
Step 1.登录OpenWeather官网并点击Sign—>create account完成注册。该网站无需魔法即可直接登录,可以使用国内邮箱或者QQ邮箱均可进行注册,官网地址为:https://openweathermap.org/
-
Step 2.获取API-key:注册完成后,即可在API keys页面查看当前账户的API key:
一般来说完成注册后,就会有一个已经激活的API-key。和OpenAI一样,OpenWeather的API key也可以创建多个。
-
Step 3.将其设置为环境变量:和OpenAI API key类似,为了方便后续调用,我们也可以直接将OpenWeather API key设置为环境变量,变量名为OPENWEATHER_API_KEY。具体设置环境变量的方法参考Ch.1中OpenAI APkey设置环境变量流程,此处不再赘述。
设置完了环境变量之后,接下来即可按照如下方式创建OpenWeather API key变量:
open_weather_key = os.getenv("OPENWEATHER_API_KEY")
4.3.3 获取实时天气信息API
import requests
# Step 1.构建请求
url = "https://api.openweathermap.org/data/2.5/weather"
# Step 2.设置查询参数
params = {
"q": "Beijing", # 查询北京实时天气
"appid": "xxx", # 输入API key
"units": "metric", # 使用摄氏度而不是华氏度
"lang":"zh_cn" # 输出语言为简体中文
}
# Step 3.发送GET请求
response = requests.get(url, params=params)
# Step 4.解析响应
data = response.json()
print(data)
# 即时温度最高、最低气温
data['main']['temp_min'], data['main']['temp_max']
# 天气状况
data['weather'][0]['description']
这里需要注意的是,城市名必须输入英文名,否则无法正确识别。
外部函数创建:我们尝试编写一个通过OpenWeather API实时获取天气信息的API,并作为模型可调用的外部函数之一。很明显,为了确保和大语言模型之间的顺畅通信,此时要求函数的输入和输出都是字符串格式。具体函数编写如下:
这里需要注意函数说明和参数解释的书写风格
def get_weather(loc):
"""
查询即时天气函数
:param loc: 必要参数,字符串类型,用于表示查询天气的具体城市名称,\
注意,中国的城市需要用对应城市的英文名称代替,例如如果需要查询北京市天气,则loc参数需要输入'Beijing';
:return:OpenWeather API查询即时天气的结果,具体URL请求地址为:https://api.openweathermap.org/data/2.5/weather\
返回结果对象类型为解析之后的JSON格式对象,并用字符串形式进行表示,其中包含了全部重要的天气信息
"""
# Step 1.构建请求
url = "https://api.openweathermap.org/data/2.5/weather"
# Step 2.设置查询参数
params = {
"q": loc,
"appid": 'xxx', # 输入API key
"units": "metric", # 使用摄氏度而不是华氏度
"lang":"zh_cn" # 输出语言为简体中文
}
# Step 3.发送GET请求
response = requests.get(url, params=params)
# Step 4.解析响应
data = response.json()
return json.dumps(data)
函数测试:
#测试函数是否可用
import json
get_weather('GuangZhou')
4.3.4 tools参数解释与定义
在准备好外部函数之后,接下来非常重要的一步就是需要将外部函数的信息以某种形式传输给模型。此时就需要使用到create函数的tools参数.从参数的具体形式来看,tools参数是一个可以包含多个字典的list,每个字典都需要包含两个键值对,分别是 {type:function,function:外部函数的完整描述}。因此每个字典都代表一个外部函数的相关信息。在大语言模型实际进行问答时,会根据tools参数提供的信息对各外部函数进行检索。
tools = [
{
"type": "function",
"function":'外部函数的完整描述'
}
]
4.3.5 外部函数完整描述
外部函数的完整描述对于Function calling功能的实现至关重要。因为在大模型进行实际问答时,会根据对外部函数的完整描述信息的语义理解进行外部函数的检索和调用。
接下来我们详细解释外部函数完整描述的指定写法。总的来说,我们会使用一个字典来对其进行完整描述,每个字典都有三个参数(三组键值对),各参数(Key)名称及解释如下:
- name:代表函数函数名称字的符串,必选参数。
- description:用于描述函数功能的字符串,虽然是可选参数,但该参数传递的信息实际上是Chat模型对函数功能识别的核心依据。即Chat函数实际上是通过每个函数的description来判断当前函数的实际功能的。
- parameters:函数的参数说明,必选参数,要求遵照JSON Schema格式进行输入,JSON Schema是一种特殊的JSON对象,专门用于验证JSON数据格式是否满足要求。
例如,对于get_weather函数,我们需要创建如下字典来对其进行完整描述:
get_weather_function = {
'name': 'get_weather',
'description': '查询即时天气函数,根据输入的城市名称,查询对应城市的实时天气',
'parameters': {
'type': 'object', #json对象类型
'properties': { #参数成员描述
'loc': {
'description': "城市名称,注意,中国的城市需要用对应城市的英文名称代替,例如如果需要查询北京市天气,则loc参数需要输入'Beijing'",
'type': 'string'
}
},
'required': ['loc']
}
}
因此修改tool参数值为:
tools = [
{
"type": "function",
"function":get_weather_function
}
]
同时还需要封装外部函数库,用于关联外部函数名称和外部函数对象
available_functions = {
"get_weather": get_weather,
}
4.3.6 Function calling实现
First response
在进行了一系列基础准备工作之后,接下来我们尝试在Chat模型对话执行Function calling功能。首先我们测试模型本身能否知道如何查询天气:
from openai import OpenAI
#硅基流动API
ds_api_key = "sk-atisrrfnrxsnuxxxkriejlfxlvnymvfxoesps"
client = OpenAI(api_key=ds_api_key,
base_url="https://api.siliconflow.cn/v1")
response = client.chat.completions.create(
model="deepseek-ai/DeepSeek-V2.5",
messages=[
{"role": "user", "content": "请帮我查询北京地区今日天气情况"}
],
)
response.choices[0].message.content
很明显,模型无法进行回答。接下来我们尝试将函数库相关信息输入给Chat模型
response = client.chat.completions.create(
model="deepseek-ai/DeepSeek-V2.5",
messages=[
{"role": "user", "content": "请帮我查询北京地区今日天气情况"}
],
tools=tools,
)
response_message = response.choices[0].message
response_message
返回结果:
ChatCompletionMessage(content='', refusal=None, role='assistant', audio=None, function_call=None, tool_calls=[ChatCompletionMessageToolCall(id='0195279d5095aab2d4ac52760de27c04', function=Function(arguments='{"loc":"Beijing"}', name='get_weather'), type='function')])
能够发现,此时返回的message中content为空,而增了一个"tool_calls"的list,该list就包含了当前调用外部函数的全部信息:
response_message.tool_calls[0]
返回结果:
ChatCompletionMessageToolCall(id='0195279d5095aab2d4ac52760de27c04', function=Function(arguments='{"loc":"Beijing"}', name='get_weather'), type='function')
对于当前CompletionMessageToolCall对象,id为外部函数调用发起请求id,function则表示调用外部函数基本信息,而type则代表了当前当前调用外部函数类型,function代表调用自定义的外部函数。
我们可以在此基础上分别提取调用外部函数名称信息和参数信息,分别保存为function_name和function_args对象:
# 完成对话需要调用的函数名称
function_name = response_message.tool_calls[0].function.name
function_name
# 基于外部函数库获取具体的函数对象
fuction_to_call = available_functions[function_name]
fuction_to_call
'''
available_functions = {
"get_weather": get_weather,
}
'''
# 执行该函数所需要的参数,将其反序列化成字典对象,便于下一步函数调用时进行传输传递
function_args = json.loads(response_message.tool_calls[0].function.arguments)
function_args
需要注意的是,外部函数的计算过程仍然是在本地执行,即Chat模型并不会将代码读取到服务器上再进行在线计算,因此接下来我们需要根据模型返回的函数和函数参数,在本地完成函数计算,然后再将计算过程和结果保存为message并追加到messages后面,并第二次调用Chat模型分析函数的计算结果,并最终根据函数计算结果输出用户问题的答案。
Second response
这里我们只需要借助**方法,直接将function_args对象传入fuction_to_call中,即可一次性传输全部参数,**方法的功能可以参考如下示例:
def function_to_call_test(a, b, c):
return a + b + c
function_args_test = {'a': 1, 'b': 2, 'c': 3}
result = function_to_call_test(**function_args_test)
print(result)
**方法其实是一种较为特殊、但同时也非常便捷的参数传递方法吗,该方法会将字典中的每个key对应的value传输到同名参数位中。接下来我们将function_args对象传入fuction_to_call中并完成计算:
function_response = fuction_to_call(**function_args) #get_weather(loc="Beijing")
function_response #获取函数调用结果
能够发现,模型已经顺利完成计算。接下来我们在messages对象中追加两条消息,第一条消息是第一次模型返回的结果(即调用模型的assistant message),第二条消息则是外部函数计算结果,该条消息的role为function,且name为函数名称。这也是我们首次接触function message,和user、system、assistant message不同,function message必须要输入关键词name,且function message的内容源于外部函数执行的计算结果,并且需要手动进行输入。具体添加过程如下:
-
追加第一条消息:模型返回的结果
#展示目前messages内容 print(messages) #将模型第一次返回的结果转换成字典类型,目的是为了将其追加到messages列表中 response_message.model_dump() # 向messages追加第一次模型返回结果消息 messages.append(response_message.model_dump()) #查看追加后的messages print(messages) -
追加第二条消息:外部函数计算结果
# 追加function返回消息 messages.append({ "role": "tool", "content": function_response, "tool_call_id":response_message.tool_calls[0].id })
接下来,再次调用Chat模型来围绕messages进行回答。需要注意的是,此时我们不再需要向模型重复提问,只需要简单的将我们已经准备好的messages传入Chat模型即可:
second_response = client.chat.completions.create(
model="deepseek-ai/DeepSeek-V2.5",
messages=messages)
second_response.choices[0].message.content
能够发现,模型最终做出了准确回答。
完整封装
def run_conv(messages,
api_key,
tools=None,
functions_list=None,
model="deepseek-ai/DeepSeek-V2.5"):
"""
能够自动执行外部函数调用的Chat对话模型
:param messages: 必要参数,输入到Chat模型的messages参数对象
:param api_key: 必要参数,调用模型的API-KEY
:param tools: 可选参数,默认为None,可以设置为包含全部外部函数的列表对象
:param model: Chat模型,可选参数,默认模型为deepseek-chat
:return:Chat模型输出结果
"""
user_messages = messages
#基于硅基流动API
client = OpenAI(api_key=api_key,
base_url="https://api.siliconflow.cn/v1")
# 如果没有外部函数库,则执行普通的对话任务
if tools == None:
response = client.chat.completions.create(
model=model,
messages=user_messages
)
final_response = response.choices[0].message.content
# 若存在外部函数库,则需要灵活选取外部函数并进行回答
else:
# 创建外部函数库字典
available_functions = {func.__name__: func for func in functions_list}
# 创建包含用户问题的message
messages = user_messages
# first response
response = client.chat.completions.create(
model=model,
messages=user_messages,
tools=tools,
)
response_message = response.choices[0].message
# 获取函数名
function_name = response_message.tool_calls[0].function.name
# 获取函数对象
fuction_to_call = available_functions[function_name]
# 获取函数参数
function_args = json.loads(response_message.tool_calls[0].function.arguments)
# 将函数参数输入到函数中,获取函数计算结果
function_response = fuction_to_call(**function_args)
# messages中拼接first response消息
user_messages.append(response_message.model_dump())
# messages中拼接外部函数输出结果
user_messages.append(
{
"role": "tool",
"content": function_response,
"tool_call_id":response_message.tool_calls[0].id
}
)
# 第二次调用模型
second_response = client.chat.completions.create(
model=model,
messages=user_messages)
# 获取最终结果
final_response = second_response.choices[0].message.content
return final_response
无需外部函数加持的情况:
messages = [{"role": "user", "content": "请问什么是机器学习?"}]
run_conv(messages=messages,
api_key = ds_api_key)
需要外部函数加持的情况:
messages = [{"role": "user", "content": "请问北京今天天气如何?"}]
run_conv(messages=messages,
api_key = ds_api_key,
tools=tools,
functions_list=[get_weather])
4.4 sql解释器Agent开发
4.4.1 项目背景
在平常的工作中,会经常对数据库中的数据进行相关的读写操作,这是一些繁杂的sql语句的编写就会尤为的麻烦也非常容易出错。尤其是在数据分析的一些业务场景中,更是需要频繁的进行数据库的相关操作且高频的编写一些对应的sql代码。
那么我们是否可以利用大模型本身的编码能力帮我们根据相关的自然语言的指令自动进行sql的编写和运行呢?
这一小节,我们就一起来学习,如何将大模型接入到本地数据库中,让大模型帮我们生成对应的sql且在本地数据库环境中进行sql的运行,将结果再次经过大模型的语义理解能力和文字生成能力进行润色后返回!
4.4.2 数据字典
对于大多数企业来说,都会围绕各关键数据集制作数据字典。所谓数据字典,指的是一份记录了每个数据集详细信息的文档,有的时候数据字典也可以以表格形式呈现。借助数据字典,开发/数据分析人员能够快速了解数据表中的各项关键信息。
那么,为了让大模型可以更好的理解数据库中的数据,我们也可以给大模型制作一个数据字典,让大模型可以更好的理解数据,返回更加具有针对性的结果。
import os
from openai import OpenAI
from IPython.display import display, Code, Markdown
#硅基流动API
ds_api_key = "sk-atisrejlfxlvnymvfxoesps"
client = OpenAI(api_key=ds_api_key,
base_url="https://api.siliconflow.cn/v1")
# 打开并读取Markdown文件
with open('./data/LC数据字典.md', 'r', encoding='utf-8') as f:
md_content = f.read()
len(md_content)
#基于md_content作为模型背景信息,向模型进行相关提问
response = client.chat.completions.create(
model="deepseek-ai/DeepSeek-V2.5",
messages=[
{"role": "system", "content": md_content},
# "content": '请帮我统计下LC数据表一共有哪些字段?共计多少个?'
{"role": "user", "content": '请帮我介绍下LC数据表'}
],
)
display(Markdown(response.choices[0].message.content))
4.4.3 Function calling实现
创建生成SQL语句的外部函数
def get_sql_result(sql_query):
"""
查询数据库相关数据的函数
:param sql_query: 必要参数,字符串类型,用于表示查询数据的sql语句;
:return:sql_query表示的sql语句查询到的结果;
"""
connection = pymysql.connect(
host='localhost', # 数据库地址
user='root', # 数据库用户名
passwd='boboadmin', # 数据库密码
db='testdb', # 数据库名
charset='utf8' # 字符集选择utf8
)
try:
with connection.cursor() as cursor:
# SQL查询语句
sql = sql_query
cursor.execute(sql)
# 获取查询结果
results = cursor.fetchall()
finally:
connection.close()
return json.dumps(results)
自动生成外部函数描述信息
import inspect
import json
import os
from openai import OpenAI
import pymysql
from IPython.display import display, Code, Markdown
#用于自动生成外部函数描述信息
def auto_function_desc(function): #参数为外部函数对象
#定义一个内部函数用于生成外部函数的完整描述信息
def inner(function):
function_description = inspect.getdoc(function)#外部函数的函数说明
function_name = function.__name__ #外部函数名
system_prompt = '以下是某的函数说明:%s' % function_description
user_prompt = '根据这个函数的函数说明,请帮我创建一个JSON格式的字典,这个字典有如下5点要求,请你仔细阅读,并且务必遵从所有要求:\
1.字典总共有三个键值对;\
2.第一个键值对的Key是字符串name,value是该函数的名字:%s,也是字符串;\
3.第二个键值对的Key是字符串description,value是该函数的函数的功能说明,也是字符串;\
4.第三个键值对的Key是字符串parameters,value是一个JSON Schema对象,用于说明该函数的参数输入规范。\
5.输出结果必须是一个JSON格式的字典,并且一定不要任何前后修饰语句,务必参按照如下格式进行输出:%s' % (function_name,'{key:value}')
api_key = "xxx"
client = OpenAI(api_key=ds_api_key,
base_url="https://api.siliconflow.cn/v1")
response = client.chat.completions.create(
model="deepseek-ai/DeepSeek-V2.5",
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_prompt}
]
)
return json.loads(response.choices[0].message.content)
#由于模型根据提示信息生成的外部函数完整信息可能会有问题,因此,如果出现问题则loads环节会报错,则要求模型重新进行生成
max_try_count = 5 #模型调用的最大次数
count = 0 #当前调用模型的次数
while count < max_try_count:
try:
function_desc = inner(function)
break
except Exception as e:
count += 1
print('something error:',e)
if count == max_try_count:
print('模型达到最大尝试次数,程序停止!')
raise
else:
print('模型重新生成中......')
tools = [
{
"type": "function",
"function":function_desc
}
]
return tools
测试:
auto_function_desc(get_sql_result)
输出:
[
{
'type': 'function',
'function': {
'name': 'get_sql_result',
'description': '查询数据库相关数据的函数',
'parameters': {
'type': 'object',
'properties': {
'sql_query': {
'type': 'string',
'description': '用于表示查询数据的sql语句'
}
},
'required': ['sql_query']}}}
]
sql解释器封装
#available_functions表示外部函数库
def auto_run_conversation(messages,available_functions=None):
api_key = "sk-atisrrfnrxsnulmuvlzqnvuvcglkriejlfxlvnymvfxoesps"
client = OpenAI(api_key=ds_api_key,
base_url="https://api.siliconflow.cn/v1")
# 如果没有外部函数库,则执行普通的对话任务
if available_functions == None:
print('模型原生能力解决该提问.........')
response = client.chat.completions.create(
model="deepseek-ai/DeepSeek-V2.5",
messages=messages
)
final_response = response.choices[0].message.content
else:
#外部函数库定义
available_functions = available_functions
#step_3:外部函数完整描述定义 + #step_4:tools参数值定义
tools = auto_function_desc(available_functions['function'])
#step_5:第一次模型调用
response = client.chat.completions.create(
model="deepseek-ai/DeepSeek-V2.5",
messages=messages,
tools=tools,
)
response_message = response.choices[0].message
#判断返回结果是否存在tool_calls,即判断是否需要调用外部函数来回答问题
if response_message.tool_calls:
print('function_calling解决该提问.........')
sql = response_message.tool_calls[0].function.arguments
print('生成的sql为::',sql)
choose = input('是否执行上述sql? y/n')
if choose == 'n':
print("您选择不执行sql语句,再见!")
return
#step_6:外部函数手动调用且获取调用结果
fuction_to_call = available_functions['function'] #函数对象
function_args = json.loads(response_message.tool_calls[0].function.arguments)#函数参数
function_response = fuction_to_call(**function_args)#函数手动调用
#step_7:向messages进行两次消息追加
messages.append(response_message.model_dump())
messages.append({
"role": "tool",
"content": function_response,
"tool_call_id":response_message.tool_calls[0].id
})
#step_8: 再次调用大模型
second_response = client.chat.completions.create(
model="deepseek-ai/DeepSeek-V2.5",
messages=messages)
final_response = second_response.choices[0].message.content
else:
final_response = response_message.content
return Markdown(final_response)
测试:
messages = [
{"role": "system", "content": md_content},
{"role": "user", "content": "请问LC数据表有多少男性用户?"}
]
#定义外部函数库
available_functions = {
"function": get_sql_result,
}
auto_run_conversation(messages,available_functions)

浙公网安备 33010602011771号