五、OpenAI实战之Assistants API

在8线小城的革委会办公室里,黑8和革委会主任的对话再次展开。

黑8:主任,您知道吗?除了OpenAI API,现在还有一项新的技术叫做Assistants API,它可以帮助我们更好地进行对话和沟通。

主任:Assistants API?听起来很神奇,它有什么特别之处吗?

黑8:是的,主任。Assistants API不仅可以生成自然流畅的文本,还能理解对话中的语境和情境,从而更加智能地回应用户的需求。它可以模拟人类对话,进行智能问答、提供建议和解决问题,为我们的工作和生活带来更多便利。

主任:这听起来确实很有用。你能举个例子吗?

黑8:当然,主任。比如,我们可以使用Assistants API来帮助进行会议记录和总结,自动生成会议纪要并提供关键信息的摘要。此外,它还可以用于客户服务,快速回答客户的问题和解决他们的疑虑,提升服务效率和用户体验。

主任:这真是太棒了!我们可以尝试将Assistants API应用到革委会的工作中,提高工作效率和质量。

黑8:是的,主任。Assistants API的应用潜力巨大,只要我们善于发挥,就能为我们的工作和使命注入新的活力和动力。

主任:谢谢你的分享,黑8。你对新技术的探索和应用态度令人钦佩,继续努力,为革委会的事业做出更多贡献。

黑8:谢谢主任的支持和鼓励,我会继续努力的。

两人在办公室里的对话结束了,但是他们对新技术的探索和应用之路才刚刚开始。通过使用Assistants API,他们将探索更多的可能性,为革委会的使命注入新的活力和动力,带领团队走向更加美好的未来。

1 Assistants API 的主要能力

已有能力:

  1. 创建和管理Assistant,每个assistant有独立的配置
  2. 支持无限长的多轮对话,对话历史保存在OpenAI的服务器上
  3. 支持Code Interpreter
    • 在沙箱里编写并运行Python代码
    • 自我修正代码
    • 可传文件给Code Interpreter
  4. 支持文件RAG
  5. 支持Function Calling

2 创建一个Assistants

可以到OpenAI Playground在线创建

3 访问Assistants

3.1 管理Thread

Threads:

  1. Threads 里保存所有历史对话(Messages)
  2. 一个Assistants可以有多个thread
  3. 每一个thread可以有无限条message
  4. 一个用户与assistant的多轮对话历史可以维护在一个thread
import jsondef show_json(obj):"""把任意对象用排版美观的 JSON 格式打印出来"""print(json.dumps(json.loads(obj.model_dump_json()),indent=4,ensure_ascii=False))
from openai import OpenAI
import osfrom dotenv import load_dotenv, find_dotenv
_ = load_dotenv(find_dotenv())# 初始化 OpenAI 服务
client = OpenAI()   # openai >= 1.3.0 起,OPENAI_API_KEY 和 OPENAI_BASE_URL 会被默认使用# 创建 thread
thread = client.beta.threads.create()
show_json(thread)

在这里插入图片描述
可以根据需要,自定义 metadata,比如创建 thread 时,把 thread 归属的用户信息存入

thread = client.beta.threads.create(metadata={"fullname": "挑大梁", "username": "jacob"}
)
show_json(thread)

在这里插入图片描述
Thread ID 如果保存下来,是可以在下次运行时继续对话的。

从 thread ID 获取 thread 对象的代码:

thread = client.beta.threads.retrieve(thread.id)
show_json(thread)

在这里插入图片描述
对metadata的操作还有:

  1. threads.update() 修改 threads
  2. threads.delete() 删除 threads

3.2 Threads中添加Messages

Messages的内容可以是:

  1. 文本、文件、图片
  2. 文本可以带参考引用
  3. metadata
message = client.beta.threads.messages.create(thread_id=thread.id,  # message 必须归属于一个 threadrole="user",          # 取值是 user 或者 assistant。但 assistant 消息会被自动加入,我们一般不需要自己构造content="你都能做什么?",
)
show_json(message)

在这里插入图片描述
对消息的操作函数还有:

  1. threads.messages.retrieve() 获取 message
  2. threads.messages.update() 更新 message 的 metadata
  3. threads.messages.list() 列出给定 thread 下的所有 messages

3.2 执行Run

  • 用 run 把 assistant 和 thread 关联,进行对话
  • 一个 prompt 就是一次 run
# assistant id 从 https://platform.openai.com/assistants 获取。你需要在自己的 OpenAI 创建一个
assistant_id = "asst_rsWrZquXB5jJsmURwaZRqoD5"run = client.beta.threads.runs.create(assistant_id=assistant_id,thread_id=thread.id,
)
show_json(run)

在这里插入图片描述
Run 是个异步调用,意味着它不等大模型处理完,就返回。我们通过 run.status 了解大模型的工作进展情况,来判断下一步该干什么。
在这里插入图片描述

import timedef wait_on_run(run, thread):"""等待 run 结束,返回 run 对象,和成功的结果"""while run.status == "queued" or run.status == "in_progress":"""还未中止"""run = client.beta.threads.runs.retrieve(thread_id=thread.id,run_id=run.id)print("status: " + run.status)# 打印调用工具的 step 详情if (run.status == "completed"):run_steps = client.beta.threads.runs.steps.list(thread_id=thread.id, run_id=run.id, order="asc")for step in run_steps.data:if step.step_details.type == "tool_calls":show_json(step.step_details)# 等待 1 秒time.sleep(1)if run.status == "requires_action":"""需要调用函数"""# 可能有多个函数需要调用,所以用循环tool_outputs = []for tool_call in run.required_action.submit_tool_outputs.tool_calls:# 调用函数name = tool_call.function.nameprint("调用函数:" + name + "()")print("参数:")print(tool_call.function.arguments)function_to_call = available_functions[name]arguments = json.loads(tool_call.function.arguments)result = function_to_call(arguments)print("结果:" + str(result))tool_outputs.append({"tool_call_id": tool_call.id,"output": json.dumps(result),})# 提交函数调用的结果run = client.beta.threads.runs.submit_tool_outputs(thread_id=thread.id,run_id=run.id,tool_outputs=tool_outputs,)# 递归调用,直到 run 结束return wait_on_run(run, thread)if run.status == "completed":"""成功"""# 获取全部消息messages = client.beta.threads.messages.list(thread_id=thread.id)# 最后一条消息排在第一位result = messages.data[0].content[0].text.valuereturn run, result# 执行失败return run, None

创建消息并运行方法:

def create_message_and_run(content, thread=None):"""创建消息和执行对象"""if not thread:thread = client.beta.threads.create()client.beta.threads.messages.create(thread_id=thread.id,role="user",content=content,)run = client.beta.threads.runs.create(assistant_id=assistant_id,thread_id=thread.id,)return run, thread

4 使用tools

4.1、创建 Assistant 时声明 Code_Interpreter

assistant = client.beta.assistants.create(name="Demo Assistant",instructions="你是人工智能助手。你可以通过代码回答很多数学问题。",tools=[{"type": "code_interpreter"}],model="gpt-4-turbo-preview"
)
run, _ = create_message_and_run("用代码计算 1234567 的平方根", thread)
run, result = wait_on_run(run, thread)
print(result)

在这里插入图片描述

4.2、创建 Assistant 时声明 Function

示例代码:


assistant = client.beta.assistants.create(instructions="你是一个助理,能干所有事情,每件任务都要细心地一步一步解决。需要时,可以向我提问以澄清不明确的指令",model="gpt-4-turbo-preview",tools=[{"type": "function","function": {"name": "tellStory","description": "Use this function to answer user questions about story."}}]
)
def tellStory(arguments):return '关于愚公移山的故事'# 可以被回调的函数放入此字典
available_functions = {"tellStory": tellStory,
}run, _ = create_message_and_run("请给我讲一个故事", thread)
run, result = wait_on_run(run, thread)
print(result)

5 内置的 RAG 功能

RAG 实际被当作一种 tool

assistant = client.beta.assistants.create(instructions="你是个问答机器人,你根据给定的知识回答用户问题。",model="gpt-4-turbo-preview",tools=[{"type": "retrieval"}],file_ids=[file.id]
)

6 多个 Assistants 协作

hats = {"蓝色" : "思考过程的控制和组织者。你负责会议的组织、思考过程的概览和总结。"+"首先,整个讨论从你开场,你只陈述问题不表达观点。最后,再由你对整个讨论做总结并给出详细的最终方案。","白色" : "负责提供客观事实和数据。你需要关注可获得的信息、需要的信息以及如何获取那些还未获得的信息。"+"思考“我们有哪些数据?我们还需要哪些信息?”等问题,并根据自己的知识或使用工具来提供答案。","红色" : "代表直觉、情感和直觉反应。不需要解释和辩解你的情感或直觉。"+"这是表达未经过滤的情绪和感受的时刻。","黑色" : "代表谨慎和批判性思维。你需要指出提案的弱点、风险以及为什么某些事情可能无法按计划进行。"+"这不是消极思考,而是为了发现潜在的问题。","黄色" : "代表乐观和积极性。你需要探讨提案的价值、好处和可行性。这是寻找和讨论提案中正面方面的时候。","绿色" : "代表创造性思维和新想法。鼓励发散思维、提出新的观点、解决方案和创意。这是打破常规和探索新可能性的时候。",
# 定义 Tool from serpapi import GoogleSearch
import osdef search(query):params = {"q": query,"hl": "en","gl": "us","google_domain": "google.com","api_key": os.environ["SERPAPI_API_KEY"]}results = GoogleSearch(params).get_dict()ans = ""for r in results["organic_results"]:ans = f"title: {r['title']}\nsnippet: {r['snippet']}\n\n"return ansavailable_functions={"search":search}
from openai import OpenAI
import osfrom dotenv import load_dotenv, find_dotenv
_ = load_dotenv(find_dotenv())# 初始化 OpenAI 服务
client = OpenAI()  
def create_assistant(color):assistant = client.beta.assistants.create(name=f"{color}帽子角色",instructions=f"我们在进行一场Six Thinking Hats讨论。按{queue}顺序。你的角色是{color}帽子。你{hats[color]}",model="gpt-3.5-turbo",tools=[{"type": "function","function": {"name": "search","description": "search the web using a search engine","parameters": {"type": "object","properties": {"query": {"type": "string","description": "space-separared keywords to search"}},"required": ["query"]}}}] if color == "白色" else [])return assistant
def update_sesssion(context, color, turn_message):context += f"\n\n{color}帽子: {turn_message}"return context
prompt_template = """
{}
======
以上是讨论的上文。
请严格按照你的角色指示,继续你的发言。直接开始你的发言内容。请保持简短。
"""def create_a_turn(assistant, context):thread = client.beta.threads.create()message = client.beta.threads.messages.create(thread_id=thread.id,  # message 必须归属于一个 threadrole="user",          # 取值是 user 或者 assistant。但 assistant 消息会被自动加入,我们一般不需要自己构造content=prompt_template.format(context),)run = client.beta.threads.runs.create(assistant_id=assistant.id,thread_id=thread.id,)return run, thread
import time, jsonstate = 0def wait_on_run(run, thread):"""等待 run 结束,返回 run 对象,和成功的结果"""def show_rolling_symbol():global statesymbols="\|/-"print(f"\r{symbols[state%4]}",end="")state += 1time.sleep(1)def hide_rolling_symbol():print("\r",end="")while run.status == "queued" or run.status == "in_progress":"""还未中止"""show_rolling_symbol()run = client.beta.threads.runs.retrieve(thread_id=thread.id,run_id=run.id)hide_rolling_symbol()if run.status == "requires_action":"""需要调用函数"""# 可能有多个函数需要调用,所以用循环tool_outputs = []for tool_call in run.required_action.submit_tool_outputs.tool_calls:# 调用函数name = tool_call.function.nameprint("调用函数:" + name + "()")print("参数:")print(tool_call.function.arguments)function_to_call = available_functions[name]arguments = json.loads(tool_call.function.arguments)result = function_to_call(**arguments)print("结果:" + str(result))tool_outputs.append({"tool_call_id": tool_call.id,"output": json.dumps(result),})# 提交函数调用的结果run = client.beta.threads.runs.submit_tool_outputs(thread_id=thread.id,run_id=run.id,tool_outputs=tool_outputs,)# 递归调用,直到 run 结束return wait_on_run(run, thread)if run.status == "completed":"""成功"""# 获取全部消息messages = client.beta.threads.messages.list(thread_id=thread.id)# 最后一条消息排在第一位result = messages.data[0].content[0].text.valuereturn run, result# 执行失败return run, None
def discuss(topic):context = f"讨论话题:{topic}\n\n[开始]\n"# 每个角色依次发言for hat in queue:print(f"---{hat}----")# 每个角色创建一个 assistantassistant = create_assistant(hat)# 创建 run 和 threadnew_turn, thread = create_a_turn(assistant, context)# 运行 run_, text = wait_on_run(new_turn, thread)print(f"{text}\n")# 更新整个对话历史context = update_sesssion(context, hat, text)

7 总结

在这里插入图片描述

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

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

相关文章

Java网络编程详解

目录 网络编程 1、概述 2、网络通信的要素 3、IP 4、端口 5、通信协议 6、TCP 文件上传 Tomcat 7、UDP 单方发送单方接受 双方发送接收 8、URL URL测试 URL下载网络资源 网络编程 1、概述 信件: 计算机网络: 计算机网络是指将地理位置不…

WPF —— TextBlock、LineBreak RadioButton控件详解

一:TextBlock 1&#xff1a;TextBlock 简介 <LineBreak/> 换行 显示文本 标签内容和content属性共存 2、TextBlock 常用的属性 Foreground&#xff1a;TextBlock的文本内容的颜色。 Background&#xff1a;背景&#xff0c;获取或设置要用于填充内容区域背景的 Brush…

冒泡排序的理解与实现【C语言、C++、java】

冒泡排序介绍 冒泡排序(Bubble Sort)&#xff0c;又被称为气泡排序或泡沫排序。 它是一种较简单的排序算法。它会遍历若干次要排序的数列&#xff0c;每次遍历时&#xff0c;它都会从前往后依次的比较相邻两个数的大小&#xff1b;如果前者比后者大&#xff0c;则交换它们的位…

一体机电脑辐射超标整改

电脑一体机是目前台式机和笔记本电脑之间的一个新型的市场产物&#xff0c;它将主机部分、显示器部分整合到一起的新形态电脑&#xff0c;该产品的创新在于内部元件的高度集成。随着无线技术的发展&#xff0c;电脑一体机的键盘、鼠标与显示器可实现无线链接&#xff0c;机器只…

美国站群服务器使用技巧与注意事项

美国站群服务器使用技巧与注意事项有哪些?RAKsmart小编为您整理发布美国站群服务器使用技巧与注意事项&#xff0c;希望对您有帮助。 美国站群服务器的使用技巧主要包括远程管理、灵活配置和备份还原&#xff0c;具体如下&#xff1a; 1. **远程管理**&#xff1a;用户可以通过…

计算机网络-第5章 运输层(2)

5.6 TCP可靠传输实现 以字节为单位的滑动窗口。 发送窗口已满&#xff0c;停止发送。 发送和接收的数据都来自缓存。 超时重传时间RTO选择&#xff1a;自适应算法&#xff0c; 选择确认SACK&#xff1a;只传送缺少的数据。大多数实现还是重传所有未被确认的数据块。 5.7 TCP的…

LLM 推理优化

LLM 推理服务重点关注两个指标&#xff1a;吞吐量和时延&#xff1a; 吞吐量&#xff1a;主要从系统的角度来看&#xff0c;即系统在单位时间内能处理的 tokens 数量。计算方法为系统处理完成的 tokens个数除以对应耗时&#xff0c;其中 tokens 个数一般指输入序列和输出序列长…

掌握Mongodb,看完这篇文章就够了

目录 1.概念 2.操作 2.1数据库操作 2.2集合操作 2.3数据操作 3.查询 4.常用技术 5.python与MongoDB 1.概念 MongoDB是一种非关系型数据库&#xff08;NoSQL&#xff09;&#xff0c;它以灵活的文档存储格式&#xff08;BSON&#xff09;和强大的查询能…

MinGW-w64的下载与安装

文章目录 1 下载2 安装3 配置环境变量4 验证 1 下载 官网地址&#xff1a;https://www.mingw-w64.org/github地址&#xff1a;https://github.com/niXman/mingw-builds-binaries/releases windows下载 跳转github下载 版本号选择&#xff1a;13.2.0是GCC的版本号&#xff1b…

如何避免MYSQL主从延迟带来的读写问题?

在MYSQL 部署架构选型上&#xff0c;许多公司都会用到主从读写分离的架构&#xff0c;如下是一个一主一从的架构&#xff0c;主库master负责写入&#xff0c;从库slave进行读取。 但是既然是读写分离&#xff0c;必然会面临这样一个问题&#xff0c;当在主库上进行更新后&#…

QML | 在QML中导入JavaScript资源、导入JavaScript资源、包含一个JavaScript 资源

01 在QML中导入JavaScript资源 JavaScript资源可以被QML文档和其他JavaScript通过相对或者绝对路径进行导入。如果使用相对路径,位置解析需要相对于包含import语句的QML文档或JavaScript资源的位置。如果JavaScript需要从网络资源中进行获取,组件的status属性会被设置为Loadi…

PyCM:Python中的混淆矩阵库

PyCM&#xff1a;Python中的混淆矩阵库 在机器学习和数据科学领域&#xff0c;评估模型的性能是至关重要的。混淆矩阵是一种常用的评估工具&#xff0c;用于可视化和量化分类模型的预测结果。PyCM是一个开源的Python库&#xff0c;提供了丰富的功能来计算和分析混淆矩阵。本文将…

【C++】STL(二) string容器

一、string基本概念 1、本质 string是C风格的字符串&#xff0c;而string本质上是一个类 string和char * 区别&#xff1a; char * 是一个指针 string是一个类&#xff0c;类内部封装了char*&#xff0c;管理这个字符串&#xff0c;是一个char*型的容器。 2、特点 1、stri…

R语言绘制桑基图教程

原文链接&#xff1a;R语言绘制桑基图教程 写在前面 在昨天3月10日&#xff0c;我们在知乎、B站等分享了功能富集桑基气泡图的绘制教程。相关链接&#xff1a;NC|高颜值功能富集桑基气泡图&#xff0c;桑基气泡组合图。 确实&#xff0c;目前这个图在文章中出现的频率相对比较…

Wilson威尔逊平滑

1、威尔逊平滑引入的动机 在曝光很少的情况下&#xff0c;计算出的CTR并不真实可靠&#xff0c;而样本数越大&#xff0c;CTR的比例才越准确&#xff0c;更能反应真实情况。 为了衡量样本数对于CTR信区间的影响&#xff0c;我们引入"威尔逊&#xff08;Wilson&#xff0…

地球系统模式(CESM)

目前通用地球系统模式&#xff08;Community Earth System Model&#xff0c;CESM&#xff09;在研究地球的过去、现在和未来的气候状况中具有越来越普遍的应用。CESM由美国NCAR于2010年07月推出以来&#xff0c;一直受到气候学界的密切关注。近年升级的CESM2.0在大气、陆地、海…

STM32CubeMX 配置 STM32F103 工程:通过DAC输出正弦波

说明&#xff1a;STM32CubeMX 配置 STM32F103 工程&#xff0c;通过DAC输出正弦波&#xff0c;参考代码可自动计算频率&#xff0c;自动计算正弦数据。 先参考这篇文章配置时钟、工程输出的设置&#xff1a; STM32CubeMX 配置 STM32F103 工程&#xff1a;通过DAC生成三角波、…

关于遗传力常见的误解

大家好&#xff0c;我是邓飞&#xff0c;今天看了一篇非常好的文章&#xff0c;介绍了遗传力相关概念和计算方法&#xff0c;里面提到了常见的误解&#xff0c;这里汇总一下。 文献链接&#xff1a;https://excellenceinbreeding.org/sites/default/files/manual/EiB-M2_Herit…

STM32CubeMX学习笔记20——SD卡FATFS文件系统

1. FATFS文件系统简介 文件系统是操作系统用于明确存储设备或分区上的文件的方法和数据结构&#xff08;即在存储设备上组织文件的方法&#xff09;。操作系统中负责管理和存储文件信息的软件机构称为文件管理系统&#xff0c;简称文件系统&#xff1b;不带文件系统的SD卡仅能…

seo js转码工具

js转码工具作用 用于把js加密 如果不想让别人看到自己的js 代码就可以使用这个方法 js工具网址 https://tool.chinaz.com/js.aspx 效果