智谱AI——智能体开发探索

Mocode 2024-08-28 08:31:03 阅读 87

智谱AI——智能体开发探索

智谱·AI开放平台:https://open.bigmodel.cn/

点击网页右上角“开发工作台”。进入工作台后,可点击进入“文档中心”。

文档中心/接口文档:https://open.bigmodel.cn/dev/api

使用指南:https://open.bigmodel.cn/dev/howuse/introduction

接口文档-开发指南探索

开发指南中,提供了三种指南:

SDK开发

提供的SDK包括Python SDK和Java SDK。

什么是SDK?

SDK,软件开发工具包(Software Development Kit),是一组代码、库、文档和示例代码,用于帮助开发者创建应用程序或软件产品。

SDK 的主要组成部分:

工具:包括编译器、调试器、构建工具等,这些工具帮助开发者编写、编译和调试代码。库:预先编写的代码库或框架,可以直接调用以实现某些功能,而无需从头开始编写代码。文档:详细的文档和指南,解释如何使用 SDK 中的各种工具和库。示例代码:提供一些示例代码,帮助开发者快速上手,了解如何实现某些功能。API:应用编程接口,定义了与操作系统、服务或其他软件进行交互的方式。

举例:

Android SDK是一种移动应用开发SDK。包含内容:Android Studio、Android API 库、调试工具、模拟器、文档、示例代码。

SDK ≠ (python)第三方库。(python)第三方库可以看作是SDK的一部分;第三方库可以独立存在,不依赖SDK(比如不需要特定的开发工具就可以使用。eg. python的第三方库的使用不需要使用指定的集成开发环境);一个SDK可以有多个第三方库。

SDK用户鉴权

SDK用户鉴权是确保只有经过授权的用户或应用程序可以访问SDK提供的功能和资源的关键机制。

在开发工作台可以查看自己的API key,并将其复制到代码中:

<code>client = ZhipuAI(api_key="......") # 请填写您自己的APIKeycode>

代码示例

智谱平台提供了三种调用方式:同步调用、异步调用和流式调用。调用方式取决于具体模型的支持情况。

观察这三种调用方法的代码,它们的不同之处主要在于为response赋值的函数不同:

同步调用、流式调用使用的函数是client.chat.completions.create,其中流式调用在函数中使用额外的参数stream。异步调用使用的函数是client.chat.asyncCompletions.create

具体内容见下文。

同步调用

调用后即可一次性获得最终结果。

代码:

from zhipuai import ZhipuAI

client = ZhipuAI(api_key="......") # 填写您自己的APIKeycode>

response = client.chat.completions.create(

model="glm-4", # 填写需要调用的模型名称code>

messages=[

{ "role": "user", "content": "作为一名营销专家,请为我的产品创作一个吸引人的slogan"},

{ "role": "assistant", "content": "当然,为了创作一个吸引人的slogan,请告诉我一些关于您产品的信息"},

{ "role": "user", "content": "智谱AI开放平台"},

{ "role": "assistant", "content": "智启未来,谱绘无限一智谱AI,让创新触手可及!"},

{ "role": "user", "content": "创造一个更精准、吸引人的slogan"}

],

)

print(response.choices[0].message)

输出:

CompletionMessage(content='"精准洞察,智谱未来 —— 携手共绘智能新篇章。"', role='assistant', tool_calls=None)code>

如果在代码的messages列表中只保留一个字典的内容,即只向模型输入“作为一名营销专家,请为我的产品创作一个吸引人的slogan”,模型的回答会类似这样:“当然可以!不过我需要先了解一些关于您产品的信息,比如产品类型、特点、目标受众等。这样我才能为您创作一个更贴切、更有吸引力的slogan。请您提供一下相关信息,我会尽快为您想出一个满意的slogan。”也就是说,在messages列表中多提供user和assistant几个回合的对话信息有机会生成更符合期望的回答(直接在第一个字典的内容中就给出产品的名称,模型也能够提供答案)。

异步调用

调用后会立即返回一个任务ID,然后用任务ID查询调用结果(根据模型和参数的不同,通常需要等待10-30秒才能得到最终结果)。

代码:

from zhipuai import ZhipuAI

client = ZhipuAI(api_key="......") # 请填写您自己的APIKeycode>

response = client.chat.asyncCompletions.create(

model="glm-4", # 填写需要调用的模型名称code>

messages=[

{

"role": "user",

"content": "请你作为童话故事大王,写一篇短篇童话故事,故事的主题是要永远保持一颗善良的心,要能够激发儿童的学习兴趣和想象力,同时也能够帮助儿童更好地理解和接受故事中所蕴含的道理和价值观。"

}

],

)

print(response)

如果运行上面的代码,只会输出如下所示任务ID,还不能得到最终的输出。

输出:

AsyncTaskStatus(id='xxxxx', request_id='xxxxx', model='glm-4', task_status='PROCESSING')code>

使用任务ID查询接口才能获取结果(如下所示),更多内容可见文档关于GLM-4的内容。

代码:

from zhipuai import ZhipuAI

import time

client = ZhipuAI(api_key="......") # 请填写您自己的APIKeycode>

response = client.chat.asyncCompletions.create(

model="glm-4", # 填写需要调用的模型名称code>

messages=[

{

"role": "user",

"content": "请你作为童话故事大王,写一篇短篇童话故事,故事的主题是要永远保持一颗善良的心,要能够激发儿童的学习兴趣和想象力,同时也能够帮助儿童更好地理解和接受故事中所蕴含的道理和价值观。"

}

],

)

print(response)

# 异步查询需要使用任务ID查询接口获取结果

task_id = response.id

task_status = ''

get_cnt = 0

while task_status != 'SUCCESS' and task_status != 'FAILED' and get_cnt <= 40: # 任务状态为PROCESSING

result_response = client.chat.asyncCompletions.retrieve_completion_result(id=task_id)

print(result_response)

task_status = result_response.task_status

time.sleep(2)

get_cnt += 1

输出:

AsyncTaskStatus(id='xxxxx', request_id='xxxxx', model='glm-4', task_status='PROCESSING')code>

...(为了节省篇幅,此处略去几行,内容与第一行一样)

AsyncCompletion(id='xxxxx', request_id='xxxxx', model='GLM-4', task_status='SUCCESS', choices=[CompletionChoice(index=0, finish_reason='stop', message=CompletionMessage(content='从前,有个名叫小明的男孩,...(为了节省篇幅,此处略去生成文本的其余内容)', role='assistant', tool_calls=None))], usage=CompletionUsage(prompt_tokens=50, completion_tokens=475, total_tokens=525), created=xxx)code>

SSE调用

调用后可以流式的实时获取到结果直到结束。

代码:

from zhipuai import ZhipuAI

client = ZhipuAI(api_key="......") # 请填写您自己的APIKeycode>

response = client.chat.completions.create(

model="glm-4", # 填写需要调用的模型名称code>

messages=[

{

"role": "user",

"content": "你好!你叫什么名字"

},

],

stream=True,

)

for chunk in response:

print(chunk.choices[0].delta)

输出:

ChoiceDelta(content='你好', role='assistant', tool_calls=None)code>

ChoiceDelta(content='!', role='assistant', tool_calls=None)code>

ChoiceDelta(content='我是一个', role='assistant', tool_calls=None)code>

ChoiceDelta(content='人工智能', role='assistant', tool_calls=None)code>

ChoiceDelta(content='助手', role='assistant', tool_calls=None)code>

ChoiceDelta(content=',', role='assistant', tool_calls=None)code>

ChoiceDelta(content='名叫', role='assistant', tool_calls=None)code>

ChoiceDelta(content='智', role='assistant', tool_calls=None)code>

ChoiceDelta(content='谱', role='assistant', tool_calls=None)code>

ChoiceDelta(content='清', role='assistant', tool_calls=None)code>

ChoiceDelta(content='言', role='assistant', tool_calls=None)code>

ChoiceDelta(content='。', role='assistant', tool_calls=None)code>

ChoiceDelta(content='很高兴', role='assistant', tool_calls=None)code>

ChoiceDelta(content='见到', role='assistant', tool_calls=None)code>

ChoiceDelta(content='你', role='assistant', tool_calls=None)code>

ChoiceDelta(content=',', role='assistant', tool_calls=None)code>

ChoiceDelta(content='并', role='assistant', tool_calls=None)code>

ChoiceDelta(content='随时', role='assistant', tool_calls=None)code>

ChoiceDelta(content='准备', role='assistant', tool_calls=None)code>

ChoiceDelta(content='回答', role='assistant', tool_calls=None)code>

ChoiceDelta(content='你的', role='assistant', tool_calls=None)code>

ChoiceDelta(content='问题和', role='assistant', tool_calls=None)code>

ChoiceDelta(content='提供', role='assistant', tool_calls=None)code>

ChoiceDelta(content='帮助', role='assistant', tool_calls=None)code>

ChoiceDelta(content='。', role='assistant', tool_calls=None)code>

ChoiceDelta(content='有什么', role='assistant', tool_calls=None)code>

ChoiceDelta(content='我可以', role='assistant', tool_calls=None)code>

ChoiceDelta(content='协助', role='assistant', tool_calls=None)code>

ChoiceDelta(content='你的', role='assistant', tool_calls=None)code>

ChoiceDelta(content='吗', role='assistant', tool_calls=None)code>

ChoiceDelta(content='?', role='assistant', tool_calls=None)code>

ChoiceDelta(content='', role='assistant', tool_calls=None)code>

HTTP调用

暂时还没探索。

第三方框架

文档提供了两个第三方框架的示例:OpenAI SDK和Langchain SDK。

OpenAI SDK

在OpenAI SDK中调用智谱AI平台中的模型(如GLM-4)与使用智谱AI的SDK调用本平台模型的代码十分相像,只是client.chat.completions.createclientZhipuAI对象变成了OpenAI对象。

代码:

from openai import OpenAI

client = OpenAI(

api_key="......", # 在智谱AI平台的api keycode>

base_url="https://open.bigmodel.cn/api/paas/v4/"code>

)

completion = client.chat.completions.create(

model="glm-4", code>

messages=[

{ "role": "system", "content": "你是一个聪明且富有创造力的小说作家"},

{ "role": "user", "content": "请你作为童话故事大王,写一篇短篇童话故事,故事的主题是要永远保持一颗善良的心,要能够激发儿童的学习兴趣和想象力,同时也能够帮助儿童更好地理解和接受故事中所蕴含的道理和价值观。"}

],

top_p=0.7,

temperature=0.9

)

print(completion.choices[0].message)

Langchain SDK

在这个框架下调用智谱AI平台中的模型(如GLM-4)似乎比使用OpenAI框架要复杂一些。这个框架可以使用Langchain的ChatOpenAI类来调用模型,也可以使用Langchain的AgentExecutor类来调用模型。

这两种类的区别跟Langchain对智能体工作流的定义有关。

使用ChatOpenAI类调用

使用ChatOpenAI类调用模型时,只需要定义llm(一个ChatOpenAI对象,用参数model指明调用哪个模型)和prompt(一个ChatPromptTemplate对象)。这种调用方式与前面使用OpenAI SDK和Zhipu SDK的方式都比较相像,都需要定义模型和输入的提示内容。

文档中提供的代码只展示了如何使用ChatOpenAI类调用GLM-4模型,该代码运行后的输出如下:

> Entering new LLMChain chain...

Prompt after formatting:

System: You are a nice chatbot having a conversation with a human.

Human: tell me a joke

> Finished chain.

输出中并不包含我们期望的回答。如果想要进一步获取回答,应该需要查看Langchain SDK的相关用法,此处暂不做探究。

使用Langchain的AgentExecutor类调用

使用AgentExecutor类调用模型时,不仅需要定义llmprompt,还需要定义tools。它们之间的关系可以参考文章《Langchain知识点(下)》中的描述。

文档提供的相关代码提到了os.environ["TAVILY_API_KEY"],这里应该是涉及到了另外一个平台tavily(一个为人工智能智能体(如大型语言模型,LLMs)和检索增强生成(RAG)应用优化的搜索引擎,旨在提供高效、快速且持久的搜索结果。更详细的内容可以参考文章《【AI】Tavily》),暂不做探究(个人暂时也没有这个平台的API key)。

在运行代码时,可以设置tools为空列表,表示不使用工具、不需要联网搜索信息、仅使用模型本身的知识来回答问题。

可以使用try子句处理agent_executor.invoke可能抛出的异常。

代码:

import os

from langchain_openai import ChatOpenAI

from langchain import hub

from langchain.agents import AgentExecutor, create_react_agent

from langchain_community.tools.tavily_search import TavilySearchResults

from langchain_community.llms import OpenAI

llm = ChatOpenAI( # Langchain的ChatOpenAI类是对OpenAI SDK的封装

temperature=0.95,

model="glm-4",code>

openai_api_key="......", # 智谱AI的API keycode>

openai_api_base="https://open.bigmodel.cn/api/paas/v4/"code>

)

# os.environ["TAVILY_API_KEY"] = "......" # tavily的API key

# tools = [TavilySearchResults(max_results=2)]

tools = []

prompt = hub.pull("hwchase17/react")

# Choose the LLM to use

agent = create_react_agent(llm, tools, prompt)

agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)

agent_executor.invoke({ "input": "what is langchain?"})

# try:

# agent_executor.invoke({"input": "what is langchain?"})

# except ValueError:

# print(ValueError)

输出(不使用联网搜索功能的情况下):

> Entering new AgentExecutor chain...

This question seems to be about a concept, and I don't know what "langchain" is. I should search for it online to get more information.

Action: search online

Action Input: langchain

Observationsearch online is not a valid tool, try one of [].Since the search online action is not available, I will attempt to answer the question based on my existing knowledge. However, I must admit that I am not familiar with the term "langchain." It is possible that it is a specialized concept in a specific field or a new term that has not gained widespread recognition yet.

Final Answer: I am not sure what "langchain" is. It may be a specialized term or a new concept that I am not familiar with. If it is related to a specific field or context, more information would be needed to provide an accurate answer.

> Finished chain.

langchain SDK的输出结构与前面几种的不同,有Action、Action Input、Observation(、Thought,一些情况下会有,自己暂时还不能明确地知道什么情况有)和Final Answer几个部分。这是比较有意思的地方,有点像chain of thought的形式,有待需要时探索。



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。