动手学大模型应用开发,第2天:调用大模型(下)

五、调用智谱 AI

1. ChatGLM 大模型

智谱 AI 是由清华大学计算机系技术成果转化而来的公司,致力于打造新一代认知智能通用模型。公司合作研发了双语千亿级超大规模预训练模型 GLM-130B,并构建了高精度通用知识图谱,形成数据与知识双轮驱动的认知引擎,基于此模型打造了 ChatGLM(chatglm.cn)。

ChatGLM 系列模型,包括 ChatGLM-130B 和 ChatGLM-6B 模型,支持相对复杂的自然语言指令,并且能够解决困难的推理类问题。其中,ChatGLM-6B 模型吸引了全球超过 160 万人下载安装,该模型在 Hugging Face (HF) 全球大模型下载榜中连续 12 天位居第一名,在国内外的开源社区中产生了较大的影响。

本章节将指导开发者如何将智谱 AI API 的使用方式,也将介绍如何将其封装成个性化 LLM 嵌入 LangChain 使用。

2. 申请调用权限

首先进入到智谱AI开放平台,点击“开始使用”或者“开发者工具台”进行注册:

如果是没有领取过免费试用包的用户,可以领取到 18 元的 token 的试用量;如下图右边绿色框所示。智谱 AI 提供了三种不同的模型 API,ChatGLM-Pro, ChatGLM-Std, ChatGLM-Lite 三种不同的模型分别适用于不同的场景,可以点击蓝色框中的立即体验直接体验。对于需要使用 API key 来搭建应用的话,需要点击右边红框中的查看 API key,就会进入到我们个人的 API 管理列表中。

在该界面,我们就可以看到我们获取到的 API 所对应的应用名字和 API key 了。

我们可以点击 添加新的 API key 并输入对应的名字即可生成新的 API key。

3. 调用智谱 AI API

智谱 AI 提供了 SDK 和原生 HTTP 来实现模型 API 的调用,建议使用 SDK 进行调用以获得更好的编程体验。

注意,需要在环境中安装配置示例中的所需第三方库。

首先我们需要配置秘钥信息:

!pip install zhipuai
import zhipuai
zhipuai.api_key = "your api key" #填写控制台中获取的 APIKey 信息model = "chatglm_std" #用于配置大模型版本

智谱的调用传参和其他类似,也需要传入一个列表,列表中包括 role 和 prompt,我们首先定义一个从用户输入 prompt 生成传入参数的函数:

def getText(role, content, text = []):# role 是指定角色,content 是 prompt 内容jsoncon = {}jsoncon["role"] = rolejsoncon["content"] = contenttext.append(jsoncon)return text

接着,我们将一个用户输入 prompt 封装为这样一个传入参数列表:

question = getText("user", "你好")
question
[{'role': 'user', 'content': '你好'}]

然后再调用 zhipuai SDK 中封装的 invoke 函数即可:

# 请求模型
response = zhipuai.model_api.invoke(model=model,prompt=question
)
print(response)
{'code': 200, 'msg': '操作成功', 'data': {'request_id': '8023318729410566227', 'task_id': '8023318729410566227', 'task_status': 'SUCCESS', 'choices': [{'role': 'assistant', 'content': '" 你好👋!我是人工智能助手 智谱清言,可以叫我小智🤖,很高兴见到你,欢迎问我任何问题。"'}], 'usage': {'prompt_tokens': 2, 'completion_tokens': 28, 'total_tokens': 30}}, 'success': True}

这里对传入 zhipuai 的参数进行简单介绍:

  • prompt (list): 调用对话模型时,将当前对话信息列表作为提示输入给模型; 按照 {"role": "user", "content": "你好"} 的键值对形式进行传参; 总长度超过模型最长输入限制后会自动截断,需按时间由旧到新排序。
  • temperature (float): 采样温度,控制输出的随机性,必须为正数。取值范围是:(0.0,1.0],不能等于 0,默认值为 0.95。值越大,会使输出更随机,更具创造性;值越小,输出会更加稳定或确定。
  • top_p (float): 用温度取样的另一种方法,称为核取样。取值范围是:(0.0, 1.0) ,开区间,不能等于 0 或 1,默认值为 0.7。模型考虑具有 top_p 概率质量 tokens 的结果。例如:0.1 意味着模型解码器只考虑从前 10% 的概率的候选集中取 tokens。
  • request_id (string): 由用户端传参,需保证唯一性;用于区分每次请求的唯一标识,用户端不传时平台会默认生成
  • return_type (string): 用于控制每次返回内容的类型,空或者没有此字段时默认按照 json_string 返回。json_string 返回标准的 JSON 字符串。text 返回原始的文本内容
  • 建议您根据应用场景调整 top_p 或 temperature 参数,但不要同时调整两个参数

4. 使用 LangChain 调用智谱 AI

我们同样可以通过 LangChain 框架来调用智谱 AI 大模型,以将其接入到我们的应用框架中。

同文心大模型类似,原生的 LangChain 是不支持智谱 AI 调用的,我们需要自定义一个 LLM。

此处,我们可以直接调用已自定义好的 ZhipuAILLM

from zhipuai_llm import ZhipuAILLM
zhipuai_model = ZhipuAILLM(model="chatglm_std", temperature=0, zhipuai_api_key=zhipuai.api_key)
zhipuai_model.generate(['你好'])
LLMResult(generations=[[Generation(text='" 你好👋!我是人工智能助手 智谱清言,可以叫我小智🤖,很高兴见到你,欢迎问我任何问题。"', generation_info=None)]], llm_output=None, run=[RunInfo(run_id=UUID('36840571-ce83-4bcb-8095-a222d59f32a4'))])

六、调用智谱 AI 生成 embedding

1. 调用智谱 AI Embedding API

智谱 AI 及ChatGLM 在上一章已经进行了简单介绍,本章将介绍如何通过其获得文本的 embedding 的,以及将其封装成个性化 embedding 嵌入 LangChain 使用。关于什么是 embedding,具体作用为何,请参见第四部分《数据库搭建》。

import zhipuai
zhipuai.api_key = "your api key" #填写控制台中获取的 APIKey 信息model = "text_embedding" #选择调用生成 embedding 的模型

自定义要生产 embedding 的文本

text = "要生成 embedding 的输入文本,字符串形式。每个输入不得超过模型的最大输入tokens数量512"

调用远程 API

response = zhipuai.model_api.invoke(model=model,prompt=text
)

官方的 SDK 返回的结果是字典的格式,这里我们可以直接传入键获得值。

我们通过查看 code 是否 == 200 来判断请求是否成功

print(response['code'])
200

返回的 embedding, token 等内容被存放在 data 中。我们可以查看生产 embedding 的长度

print(f"生成的 embedding 长度为: {len(response['data']['embedding'])}")
生成的 embedding 长度为: 1024

对于每次模型的调用来说,都是要消耗 token 的(花钱),token 的消耗都存放在 data 的 usage 中。

一般情况下 ChatGLM 模型中 token 和字数的换算比例约为 1:1.8,但因为不同模型的分词不同,所以换算比例也存在差异,每一次实际处理 token 数量以模型返回为准。

我们可以查看输入的 tokens

print(f"用户输入的 tokens 数量为: {response['data']['usage']['prompt_tokens']}")
用户输入的 tokens 数量为: 28
print(f"用户输入的文本长度为: {len(text)}")
用户输入的文本长度为: 52
print(f"本次 token 和字数的换算比例为: {response['data']['usage']['prompt_tokens']/len(text)}, 和理论值 1:1.8 = {1/1.8} 接近")
本次 token 和字数的换算比例为: 0.5384615384615384, 和理论值 1:1.8 = 0.5555555555555556 接近

因为模型其实没有生成新的文本,只是获取到输入的 embedding,所以 token 数为0

print(f"模型输出的 tokens 数量为: {response['data']['usage']['completion_tokens']}")
模型输出的 tokens 数量为: 0
print(f"总 tokens 数量为: {response['data']['usage']['total_tokens']}")
总 tokens 数量为: 28

2. 使用 LangChain 调用智谱 AI Embedding

我们同样可以通过 LangChain 框架来调用智谱 AI 大模型,以将其接入到我们的应用框架中。

原生的 LangChain 是不支持智谱 AI Embedding 调用的,我们需要自定义一个 Embedding。

此处,我们可以直接调用已自定义好的 ZhipuAILLM

import zhipuai
from zhipuai_embedding import ZhipuAIEmbeddings
zhipuai.api_key = "xxx"     #输入你的 api_key
zhipuai_embeddings = ZhipuAIEmbeddings(zhipuai_api_key=zhipuai.api_key)

我们可以生成 query 的 embedding。

query_embedding = zhipuai_embeddings.embed_query('你好')print(query_embedding[:10])
[-0.13970163464546204, 0.04416792839765549, 0.020967043936252594, -0.19684536755084991, 0.08451296389102936, -0.0685092955827713, -0.05186789482831955, 0.11296232044696808, 0.12375720590353012, 0.1507660448551178]

我们也可以生成 doc_list 的 embedding。

doc_list = ['你好','什么是机器学习','什么是深度学习','什么是大模型'
]doc_embeddings = zhipuai_embeddings.embed_documents(doc_list)
print('\n'.join([f'{doc} 的 embedding 为 {doc_embedding[:10]}...\n' for doc, doc_embedding in zip(doc_list, doc_embeddings)]))
你好 的 embedding 为 [-0.13970163464546204, 0.04416792839765549, 0.020967043936252594, -0.19684536755084991, 0.08451296389102936, -0.0685092955827713, -0.05186789482831955, 0.11296232044696808, 0.12375720590353012, 0.1507660448551178]...什么是机器学习 的 embedding 为 [-0.04628180339932442, -0.09553179144859314, 0.010844158940017223, -0.1201983317732811, 0.16935010254383087, -0.15349552035331726, 0.17940732836723328, 0.1256963312625885, 0.09910263121128082, 0.1022590845823288]...什么是深度学习 的 embedding 为 [-0.09552870690822601, -0.03116282820701599, 0.11060678958892822, 0.08925414085388184, 0.06898286193609238, -0.07559530436992645, 0.2021033763885498, -0.04418506473302841, 0.10697835683822632, -0.0666293203830719]...什么是大模型 的 embedding 为 [0.10551410913467407, 0.1735556423664093, -0.24402201175689697, 0.02649446204304695, 0.09757085889577866, 0.030247822403907776, 0.4318920969963074, 0.06334380805492401, -0.02869655191898346, -0.1011139303445816]...

七、langchain 核心组件详解

1. 模型输入/输出

LangChain 中模型输入/输出模块是与各种大语言模型进行交互的基本组件,是大语言模型应用的核心元素。模型 I/O 允许您管理 prompt(提示),通过通用接口调用语言模型以及从模型输出中提取信息。该模块的基本流程如下图所示。

主要包含以下部分:PromptsLanguage Models以及 Output Parsers用户原始输入与模型和示例进行组合,然后输入给大语言模型,再根据大语言模型的返回结果进行输出或者结构化处理

2. 数据连接

大语言模型(Large Language Model, LLM), 比如 ChatGPT , 可以回答许多不同的问题。但是大语言模型的知识来源于其训练数据集,并没有用户的信息(比如用户的个人数据,公司的自有数据),也没有最新发生时事的信息(在大模型数据训练后发表的文章或者新闻) 。因此大模型能给出的答案比较受限。如果能够让大模型在训练数据集的基础上,利用我们自有数据中的信息来回答我们的问题,那便能够得到更有用的答案。

为了支持上述应用的构建,LangChain 数据连接(Data connection)模块通过以下方式提供组件来加载、转换、存储和查询数据Document loadersDocument transformersText embedding modelsVector stores 以及 Retrievers。数据连接模块部分的基本框架如下图所示。

3. 链(Chain)

虽然独立使用大型语言模型能够应对一些简单任务,但对于更加复杂的需求,可能需要将多个大型语言模型进行链式组合,或与其他组件进行链式调用。链允许将多个组件组合在一起,创建一个单一的、连贯的应用程序。例如,可以创建一个链,接受用户输入,使用 PromptTemplate 对其进行格式化,然后将格式化后的提示词传递给大语言模型。也可以通过将多个链组合在一起或将链与其他组件组合来构建更复杂的链。

大语言模型链(LLMChain)是一个简单但非常强大的链,也是后面我们将要介绍的许多链的基础。我们以它为例,进行介绍:

import warnings
warnings.filterwarnings('ignore')from langchain.chat_models import ChatOpenAI 
from langchain.prompts import ChatPromptTemplate  
from langchain.chains import LLMChain  # 这里我们将参数temperature设置为0.0,从而减少生成答案的随机性。
# 如果你想要每次得到不一样的有新意的答案,可以尝试调整该参数。
llm = ChatOpenAI(temperature=0.0)  #初始化提示模版
prompt = ChatPromptTemplate.from_template("描述制造{product}的一个公司的最佳名称是什么?")#将大语言模型(LLM)和提示(Prompt)组合成链
chain = LLMChain(llm=llm, prompt=prompt)#运行大语言模型链
product = "大号床单套装"
chain.run(product)

运行输出:

'"豪华床纺"'

除了上例中给出的 LLMChain,LangChain 中链还包含 RouterChain、SimpleSequentialChain、SequentialChain、TransformChain 等。

  • RouterChain 可以根据输入数据的某些属性/特征值,选择调用不同的子链(Subchain)。
  • SimpleSequentialChain 是最简单的序列链形式,其中每个步骤具有单一的输入/输出,上一个步骤的输出是下一个步骤的输入
  • SequentialChain 是简单顺序链的更复杂形式,允许多个输入/输出
  • TransformChain 可以引入自定义转换函数,对输入进行处理后进行输出

以下是使用 SimpleSequentialChain 的代码示例:

from langchain.chains import SimpleSequentialChain
llm = ChatOpenAI(temperature=0.9)#创建两个子链# 提示模板 1 :这个提示将接受产品并返回最佳名称来描述该公司
first_prompt = ChatPromptTemplate.from_template(   "描述制造{product}的一个公司的最好的名称是什么"
)
chain_one = LLMChain(llm=llm, prompt=first_prompt)# 提示模板 2 :接受公司名称,然后输出该公司的长为20个单词的描述
second_prompt = ChatPromptTemplate.from_template(   "写一个20字的描述对于下面这个\公司:{company_name}的"
)
chain_two = LLMChain(llm=llm, prompt=second_prompt)#构建简单顺序链
#现在我们可以组合两个LLMChain,以便我们可以在一个步骤中创建公司名称和描述
overall_simple_chain = SimpleSequentialChain(chains=[chain_one, chain_two], verbose=True)#运行简单顺序链
product = "大号床单套装"
overall_simple_chain.run(product)

运行输出:

> Entering new SimpleSequentialChain chain...
优床制造公司
优床制造公司是一家专注于生产高品质床具的公司。> Finished chain.'优床制造公司是一家专注于生产高品质床具的公司。'

4. 记忆(Memory)

在 LangChain 中,记忆(Memory)指的是大语言模型(LLM)的短期记忆。为什么是短期记忆?那是因为LLM训练好之后 (获得了一些长期记忆),它的参数便不会因为用户的输入而发生改变。当用户与训练好的LLM进行对话时,LLM 会暂时记住用户的输入和它已经生成的输出,以便预测之后的输出,而模型输出完毕后,它便会“遗忘”之前用户的输入和它的输出。因此,之前的这些信息只能称作为 LLM 的短期记忆。

正如上面所说,在与语言模型交互时,你可能已经注意到一个关键问题:它们并不记忆你之前的交流内容,这在我们构建一些应用程序(如聊天机器人)的时候,带来了很大的挑战,使得对话似乎缺乏真正的连续性。因此,在本节中我们将介绍 LangChain 中的记忆模块,即如何将先前的对话嵌入到语言模型中的,使其具有连续对话的能力。

5. 代理(Agents)

大型语言模型(LLMs)非常强大,但它们缺乏“最笨”的计算机程序可以轻松处理的特定能力。LLM 对逻辑推理、计算和检索外部信息的能力较弱,这与最简单的计算机程序形成对比。例如,语言模型无法准确回答简单的计算问题,还有当询问最近发生的事件时,其回答也可能过时或错误,因为无法主动获取最新信息。这是由于当前语言模型仅依赖预训练数据,与外界“断开”。要克服这一缺陷, LangChain 框架提出了 “代理”( Agent ) 的解决方案。代理作为语言模型的外部模块,可提供计算、逻辑、检索等功能的支持,使语言模型获得异常强大的推理和获取信息的超能力

6.回调(Callback)

LangChain提供了一个回调系统,允许您连接到LLM应用程序的各个阶段。这对于日志记录、监视、流式处理和其他任务非常有用

Callback 模块扮演着记录整个流程运行情况的角色,充当类似于日志的功能。在每个关键节点,它记录了相应的信息,以便跟踪整个应用的运行情况。例如,在 Agent 模块中,它记录了调用 Tool 的次数以及每次调用的返回参数值。Callback 模块可以将收集到的信息直接输出到控制台,也可以输出到文件,甚至可以传输到第三方应用程序,就像一个独立的日志管理系统一样。通过这些日志,可以分析应用的运行情况,统计异常率,并识别运行中的瓶颈模块以进行优化。

Callback 模块的具体实现包括两个主要功能,对应CallbackHandler 和 CallbackManager 的基类功能:

  • CallbackHandler 用于记录每个应用场景(如 Agent、LLchain 或 Tool )的日志,它是单个日志处理器,主要记录单个场景的完整日志信息。
  • 而CallbackManager则封装和管理所有的 CallbackHandler ,包括单个场景的处理器,也包括整个运行时链路的处理器。"

在哪里传入回调 ?

该参数可用于整个 API 中的大多数对象(链、模型、工具、代理等),位于两个不同位置::

构造函数回调:在构造函数中定义,例如 LLMChain(callbacks=[handler], tags=['a-tag']) ,它将被用于对该对象的所有调用,并且将只针对该对象,例如,如果你向 LLMChain 构造函数传递一个 handler ,它将不会被附属于该链的 Model 使用。

请求回调:定义在用于发出请求的 call() / run() / apply() 方法中,例如 chain.call(inputs, callbacks=[handler]) ,它将仅用于该特定请求,以及它包含的所有子请求(例如,对 LLMChain 的调用会触发对 Model 的调用,该 Model 使用 call() 方法中传递的相同 handler)。

verbose 参数在整个 API 的大多数对象(链、模型、工具、代理等)上都可以作为构造参数使用,例如 LLMChain(verbose=True),它相当于将 ConsoleCallbackHandler 传递给该对象和所有子对象的 callbacks 参数。这对调试很有用,因为它将把所有事件记录到控制台。

你想在什么时候使用这些东西呢?

构造函数回调对诸如日志、监控等用例最有用,这些用例不是针对单个请求,而是针对整个链。例如,如果你想记录所有向 LLMChain 发出的请求,你可以向构造函数传递一个处理程序。

请求回调对流媒体等用例最有用,你想把单个请求的输出流向特定的 websocket 连接,或其他类似用例。例如,如果你想把单个请求的输出流到一个 websocket ,你会把一个处理程序传递给 call() 方法.

关于langchain组件的更多使用方法和示例,可以参考以下材料:

  1. langchain 官方文档
  2. 面向开发者的 LLM 入门课程

八、总结

在本章中,我们简要介绍了四种常用大模型 API 的调用方式:ChatGPT、百度文心、讯飞星火、智谱 AI。四种模型 API 都具有不同的调用要求,我们分别进行了介绍并对其原生接口进行了封装,方便用户直接调用使用;同时,我们也简要介绍了如何将大模型 API 封装到 LangChain 的自定义 LLM 中,如何将大模型 API 封装成统一方式调用的本地 API,以及如何将大模型 Embedding API 封装到 LangChain 的自定义 LLM 中。我们分别以百度文心、讯飞星火、智谱 AI作为示例介绍了调用方式,欢迎读者们自行实践尝试将更多的模型进行统一封装。

学习完本章,你应该掌握了常用大模型的基本调用方式,那么接下来,你就可以开始着手基于大模型打造自己的应用啦!


以上所有代码仅为思路,因API更新太快,请以官方文档为准!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/877605.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《浅谈树拓扑序计数相关问题的一些方法》阅读笔记

才发现原来我不会拓扑序计数。临时补一下。树拓扑序计数 叶向树拓扑序计数 朴素的做法是 dp 然后归纳,但是论文给出了新解释。 考察一个简单的拓扑序生成方式:你有一个集合,初始为空,每次选择树中不在集合里的一个点,取它最浅的不在集合里的点,加入集合,重复操作 \(n\) …

MyBatis之万能的map

在映射的mxl文件中写sql语句时,可以将parameterType设置为map,这样就可以想传什么就传什么,废话不多说,上代码 insertUser2和insertUser的区别是,前者传递的是map,后者传递的是User类,如果User类的属性很多的话,后者这种传递方式需要定义一个对象,并且实现每一个属性…

昆明理工大学计算机25考研面试真题

--昆工昆明理工大学计算机技术人工智能软件工程网络空间安全计算机系统结构计算机软件与理论计算机应用技术网络与信息安全408考研综合程序设计891计算机专业核心综合数据库系统原理

提示工程 (Prompt Engineering)

概念 提示工程也叫 指令工程。调优不知道训练数据怎么办?高质量prompt 核心要点:具体、丰富、少歧义本文来自博客园,作者:chuangzhou,转载请注明原文链接:https://www.cnblogs.com/czzz/p/18696337

线段树优化建树 CF786B

题解,线段树优化建图。看到区间操作想到用线段树优化建树,建一棵外向树一棵内向树,用线段树点代表整个区间内的所有点。 大佬的图从树上找节点然后连边就可以,最后跑个dijktra就完成了。 我一次就过样例了,改了几次内存就过了这题,太好了!!! #include <bits/stdc++…

数据库安全管理中的用户和角色管理:打造安全高效的数据环境

title: 数据库安全管理中的用户和角色管理:打造安全高效的数据环境 date: 2025/2/1 updated: 2025/2/1 author: cmdragon excerpt: 在数字化时代,数据库作为信息存储和处理的核心,安全管理显得尤为重要。用户和角色管理是保障数据库安全性的重要手段,合理的管理策略不仅能…

如何成为销售顶尖高手?这4个方法绝了!

在销售的世界里,业绩高手们总有一套独特的“制胜法则”。他们不仅对产品了如指掌,更擅长与客户沟通,能够在复杂多变的市场中游刃有余,稳操胜券。玩变化:灵活应变,精准出击 高手们深知,销售没有一成不变的模式。他们懂得根据不同客户、场合和时间,灵活调整沟通方式和销售…

分布式事务之2PC两阶段提交

1. 分布式事务概述 1.1 问题背景 在分布式系统中,业务操作可能跨越多个服务或数据库(如订单服务、库存服务、支付服务),传统单机事务(ACID)无法满足跨网络节点的数据一致性需求。网络不可靠:服务间调用可能失败或超时。 数据一致性:不同节点间的状态需最终一致。 性能与…

【SQL】存储过程、函数、触发器

存储过程 存储过程(Stored Procedure)是一种在数据库中保存的SQL语句集合,它可以执行一系列的数据库操作,例如插入、更新、查询等。存储过程可以提高数据库操作的效率,减少网络流量,并且可以封装复杂的逻辑。定义: 存储过程是一组为了完成特定功能的SQL语句集,这些语句…

[Tools] GitHub Action 部署文档网站

关于部署网站,理论上来讲,只要你有一个服务器,你要采用什么样的方式来部署都是可以的。但是前提是你需要有一个服务器(物理机、云服务器)。 这节课我们部署文档网站选择使用 github 来进行部署,因为 GitHub 为我们提供了一个免费的服务器,一个账号只有一个,只要你在 Gi…

[Tools] VitePress搭建文档网站

创建 API 文档可以选择如下的 3 种方式:功能较少,可以直接写在 README.md 文件里面 内容较多,可以单独写一个文件 API 数量众多(Vue、React 这种级别),需要考虑单独拿一个网站来做详细的文档支持这里我们要搭建的网站实际上就是一个文档网站,这个时候我们可以选择静态站…