成都的教育品牌网站建设/网络培训心得
前言
2023 年 11 月 6 日,OpenAI DevDay 发表了一系列新能力,其中包括:GPT Store 和 Assistants API。
GPTs 和 Assistants API 本质是降低开发门槛
可操控性和易用性之间的权衡与折中:
- 更多技术路线选择:原生 API、GPTs 和 Assistants API
- GPTs 的示范,起到教育客户的作用,有助于打开市场
- 要更大自由度,需要用 Assistants API 开发
- 想极致调优,还得原生 API + RAG
- 国内大模型的 Assistants API,参考 Minimax
Assistants API 的主要能力
已有能力:
- 创建和管理 assistant,每个 assistant 有独立的配置
- 支持无限长的多轮对话,对话历史保存在 OpenAI 的服务器上
- 通过自有向量数据库支持基于文件的 RAG
- 支持 Code Interpreter
- 在沙箱里编写并运行 Python 代码
- 自我修正代码
- 可传文件给 Code Interpreter
- 支持 Function Calling
- 支持在线调试的 Playground
承诺未来会有的能力:
- 支持 DALL·E
- 支持图片消息
- 支持自定义调整 RAG 的配置项
收费:
- 按 token 收费。无论多轮对话,还是 RAG,所有都按实际消耗的 token 收费
- 如果对话历史过多超过大模型上下文窗口,会自动放弃最老的对话消息
- 文件按数据大小和存放时长收费。1 GB 向量存储 一天收费 0.10 美元
- Code interpreter 跑一次 $0.03
创建一个 Assistant
可以为每个应用,甚至应用中的每个有对话历史的使用场景,创建一个 assistant。
虽然可以用代码创建,也不复杂,例如:
from openai import OpenAI# 初始化 OpenAI 服务
client = OpenAI()# 创建助手
assistant = client.beta.assistants.create(name="小U",instructions="你叫小U,你是JAVA技术框架 UAP的助手,你负责回答用户关于UAP的问题。",model="gpt-4-turbo",
)
但是,更佳做法是,到 Playground 在线创建,因为:
- 更方便调整
- 更方便测试
样例 Assistant 的配置
Instructions:
你叫小U,你是JAVA技术框架 UAP的助手,你负责回答用户关于UAP的问题。
Functions:
{"name": "ask_database","description": "Use this function to answer user questions about course schedule. Output should be a fully formed SQL query.","parameters": {"type": "object","properties": {"query": {"type": "string","description": "SQL query extracting info to answer the user's question.\nSQL should be written using this database schema:\n\nCREATE TABLE Courses (\n\tid INT AUTO_INCREMENT PRIMARY KEY,\n\tcourse_date DATE NOT NULL,\n\tstart_time TIME NOT NULL,\n\tend_time TIME NOT NULL,\n\tcourse_name VARCHAR(255) NOT NULL,\n\tinstructor VARCHAR(255) NOT NULL\n);\n\nThe query should be returned in plain text, not in JSON.\nThe query should only contain grammars supported by SQLite."}},"required": ["query"]}
}
代码访问 Assistant
管理 thread
Threads:
- Threads 里保存的是对话历史,即 messages
- 一个 assistant 可以有多个 thread
- 一个 thread 可以有无限条 message
- 一个用户与 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)
{"id": "thread_zkT0xybD8VslhJzJJNY3IHuX","created_at": 1716553797,"metadata": {},"object": "thread","tool_resources": {"code_interpreter": null,"file_search": null} }
可以根据需要,自定义 metadata
,比如创建 thread 时,把 thread 归属的用户信息存入。
thread = client.beta.threads.create(metadata={"fullname": "王卓然", "username": "taliux"}
)
show_json(thread)
{"id": "thread_1LMmbLMx2ZrRQjymDOGQGYGX","created_at": 1716553801,"metadata": {"fullname": "王卓然","username": "taliux"},"object": "thread","tool_resources": {"code_interpreter": null,"file_search": null} }
Thread ID 如果保存下来,是可以在下次运行时继续对话的。
从 thread ID 获取 thread 对象的代码:
thread = client.beta.threads.retrieve(thread.id)
show_json(thread)
{"id": "thread_1LMmbLMx2ZrRQjymDOGQGYGX","created_at": 1716553801,"metadata": {"fullname": "王卓然","username": "taliux"},"object": "thread","tool_resources": {"code_interpreter": {"file_ids": []},"file_search": null} }
此外,还有:
threads.modify()
修改 thread 的metadata
和tool_resources
threads.retrieve()
获取 threadthreads.delete()
删除 thread。
具体文档参考:https://platform.openai.com/docs/api-reference/threads
给 Threads 添加 Messages
这里的 messages 结构要复杂一些:
- 不仅有文本,还可以有图片和文件
- 也有
metadata
message = client.beta.threads.messages.create(thread_id=thread.id, # message 必须归属于一个 threadrole="user", # 取值是 user 或者 assistant。但 assistant 消息会被自动加入,我们一般不需要自己构造content="你都能做什么?",
)
show_json(message)
{"id": "msg_wDZxbO2oi2rAvk9Yxgqw0hVP","assistant_id": null,"attachments": [],"completed_at": null,"content": [{"text": {"annotations": [],"value": "你都能做什么?"},"type": "text"}],"created_at": 1716553809,"incomplete_at": null,"incomplete_details": null,"metadata": {},"object": "thread.message","role": "user","run_id": null,"status": null,"thread_id": "thread_1LMmbLMx2ZrRQjymDOGQGYGX" }
还有如下函数:
threads.messages.retrieve()
获取 messagethreads.messages.update()
更新 message 的metadata
threads.messages.list()
列出给定 thread 下的所有 messages
具体文档参考:https://platform.openai.com/docs/api-reference/messages
也可以在创建 thread 同时初始化一个 message 列表:
thread = client.beta.threads.create(messages=[{"role": "user","content": "你好",},{"role": "assistant","content": "有什么可以帮您?",},{"role": "user","content": "你是谁?",},]
)show_json(thread) # 显示 thread
print("-----")
show_json(client.beta.threads.messages.list(thread.id)) # 显示指定 thread 中的 message 列表
{"id": "thread_Qf32rY62YZrpW8d3nEm51mLn","created_at": 1716553813,"metadata": {},"object": "thread","tool_resources": {"code_interpreter": null,"file_search": null} } ----- {"data": [{"id": "msg_MkAm2f87yE3ynnLOzXCLq5XR","assistant_id": null,"attachments": [],"completed_at": null,"content": [{"text": {"annotations": [],"value": "你是谁?"},"type": "text"}],"created_at": 1716553813,"incomplete_at": null,"incomplete_details": null,"metadata": {},"object": "thread.message","role": "user","run_id": null,"status": null,"thread_id": "thread_Qf32rY62YZrpW8d3nEm51mLn"},{"id": "msg_tTgI3MS6t19pzQM7ItFJkZaA","assistant_id": null,"attachments": [],"completed_at": null,"content": [{"text": {"annotations": [],"value": "有什么可以帮您?"},"type": "text"}],"created_at": 1716553813,"incomplete_at": null,"incomplete_details": null,"metadata": {},"object": "thread.message","role": "assistant","run_id": null,"status": null,"thread_id": "thread_Qf32rY62YZrpW8d3nEm51mLn"},{"id": "msg_imlUh5ckePY0SaBmE6dDB3AY","assistant_id": null,"attachments": [],"completed_at": null,"content": [{"text": {"annotations": [],"value": "你好"},"type": "text"}],"created_at": 1716553813,"incomplete_at": null,"incomplete_details": null,"metadata": {},"object": "thread.message","role": "user","run_id": null,"status": null,"thread_id": "thread_Qf32rY62YZrpW8d3nEm51mLn"}],"object": "list","first_id": "msg_MkAm2f87yE3ynnLOzXCLq5XR","last_id": "msg_imlUh5ckePY0SaBmE6dDB3AY","has_more": false }
开始 Run
- 用 run 把 assistant 和 thread 关联,进行对话
- 一个 prompt 就是一次 run
直接运行
assistant_id = "asst_pxKAiBW0VB62glWPjeRDA7mR" # 从 Playground 中拷贝run = client.beta.threads.runs.create_and_poll(thread_id=thread.id,assistant_id=assistant_id,
)
if run.status == 'completed':messages = client.beta.threads.messages.list(thread_id=thread.id)show_json(messages)
else:print(run.status)
Run 的状态
Run 的底层是个异步调用,意味着它不等大模型处理完,就返回。我们通过 run.status
了解大模型的工作进展情况,来判断下一步该干什么。
run.status
有的状态,和状态之间的转移关系如图。
流式运行
- 创建回调函数
from typing_extensions import override
from openai import AssistantEventHandlerclass EventHandler(AssistantEventHandler):@overridedef on_text_created(self, text) -> None:"""响应输出创建事件"""print(f"\nassistant > ", end="", flush=True)@overridedef on_text_delta(self, delta, snapshot):"""响应输出生成的流片段"""print(delta.value, end="", flush=True)
2. 运行 run
# 添加新一轮的 user message
message = client.beta.threads.messages.create(thread_id=thread.id,role="user",content="你说什么?",
)
# 使用 stream 接口并传入 EventHandler
with client.beta.threads.runs.stream(thread_id=thread.id,assistant_id=assistant_id,event_handler=EventHandler(),
) as stream:stream.until_done()
还有如下函数:
threads.runs.list()
列出 thread 归属的 runthreads.runs.retrieve()
获取 runthreads.runs.update()
修改 run 的 metadatathreads.runs.cancel()
取消in_progress
状态的 run
具体文档参考:https://platform.openai.com/docs/api-reference/runs
使用 Tools
创建 Assistant 时声明 Code_Interpreter
如果用代码创建:
assistant = client.beta.assistants.create(name="Demo Assistant",instructions="你是人工智能助手。你可以通过代码回答很多数学问题。",tools=[{"type": "code_interpreter"}],model="gpt-4-turbo"
)
在回调中加入 code_interpreter 的事件响应
from typing_extensions import override
from openai import AssistantEventHandlerclass EventHandler(AssistantEventHandler):@overridedef on_text_created(self, text) -> None:"""响应输出创建事件"""print(f"\nassistant > ", end="", flush=True)@overridedef on_text_delta(self, delta, snapshot):"""响应输出生成的流片段"""print(delta.value, end="", flush=True)@overridedef on_tool_call_created(self, tool_call):"""响应工具调用"""print(f"\nassistant > {tool_call.type}\n", flush=True)@overridedef on_tool_call_delta(self, delta, snapshot):"""响应工具调用的流片段"""if delta.type == 'code_interpreter':if delta.code_interpreter.input:print(delta.code_interpreter.input, end="", flush=True)if delta.code_interpreter.outputs:print(f"\n\noutput >", flush=True)for output in delta.code_interpreter.outputs:if output.type == "logs":print(f"\n{output.logs}", flush=True)
发个 Code Interpreter 请求:
# 创建 thread
thread = client.beta.threads.create()# 添加新一轮的 user message
message = client.beta.threads.messages.create(thread_id=thread.id,role="user",content="用代码计算 1234567 的平方根",
)
# 使用 stream 接口并传入 EventHandler
with client.beta.threads.runs.stream(thread_id=thread.id,assistant_id=assistant_id,event_handler=EventHandler(),
) as stream:stream.until_done()
assistant > code_interpreterimport math# 计算 1234567 的平方根 square_root = math.sqrt(1234567) square_rootoutput >1111.1107055554814assistant > 1234567 的平方根是约 1111.11。
Code_Interpreter 操作文件
# 上传文件到 OpenAI
file = client.files.create(file=open("mydata.csv", "rb"),purpose='assistants'
)# 创建 assistant
my_assistant = client.beta.assistants.create(name="CodeInterpreterWithFileDemo",instructions="你是数据分析师,按要求分析数据。",model="gpt-4-turbo",tools=[{"type": "code_interpreter"}],tool_resources={"code_interpreter": {"file_ids": [file.id] # 为 code_interpreter 关联文件}}
)
# 创建 thread
thread = client.beta.threads.create()# 添加新一轮的 user message
message = client.beta.threads.messages.create(thread_id=thread.id,role="user",content="统计总销售额",
)
# 使用 stream 接口并传入 EventHandler
with client.beta.threads.runs.stream(thread_id=thread.id,assistant_id=my_assistant.id,event_handler=EventHandler(),
) as stream:stream.until_done()
关于文件操作,还有如下函数:
client.files.list()
列出所有文件client.files.retrieve()
获取文件对象client.files.delete()
删除文件client.files.content()
读取文件内容
具体文档参考:https://platform.openai.com/docs/api-reference/files
创建 Assistant 时声明 Function
如果用代码创建:'''
python
assistant = client.beta.assistants.create(instructions="你叫瓜瓜。你是AGI课堂的助手。你只回答跟AI大模型有关的问题。不要跟学生闲聊。每次回答问题前,你要拆解问题并输出一步一步的思考过程。",model="gpt-4o",tools=[{"type": "function","function": {"name": "ask_database","description": "Use this function to answer user questions about course schedule. Output should be a fully formed SQL query.","parameters": {"type": "object","properties": {"query": {"type": "string","description": "SQL query extracting info to answer the user's question.\nSQL should be written using this database schema:\n\nCREATE TABLE Courses (\n\tid INT AUTO_INCREMENT PRIMARY KEY,\n\tcourse_date DATE NOT NULL,\n\tstart_time TIME NOT NULL,\n\tend_time TIME NOT NULL,\n\tcourse_name VARCHAR(255) NOT NULL,\n\tinstructor VARCHAR(255) NOT NULL\n);\n\nThe query should be returned in plain text, not in JSON.\nThe query should only contain grammars supported by SQLite."}},"required": ["query"]}}]
)
'''
创建一个 Function
# 定义本地函数和数据库import sqlite3# 创建数据库连接
conn = sqlite3.connect(':memory:')
cursor = conn.cursor()# 创建orders表
cursor.execute("""
CREATE TABLE Courses (id INT AUTO_INCREMENT PRIMARY KEY,course_date DATE NOT NULL,start_time TIME NOT NULL,end_time TIME NOT NULL,course_name VARCHAR(255) NOT NULL,instructor VARCHAR(255) NOT NULL
);
""")# 插入5条明确的模拟记录
timetable = [('2024-01-23', '20:00', '22:00', 'aaaaa', '张三'),('2024-01-25', '20:00', '22:00', 'bbbbbbbb', '张三'),('2024-01-29', '20:00', '22:00', 'ccccc', '张三'),('2024-02-20', '20:00', '22:00', 'dddddd', '张三'),('2024-02-22', '20:00', '22:00', 'eeeeeee', '李四'),]for record in timetable:cursor.execute('''INSERT INTO Courses (course_date, start_time, end_time, course_name, instructor)VALUES (?, ?, ?, ?, ?)''', record)# 提交事务
conn.commit()def ask_database(query):cursor.execute(query)records = cursor.fetchall()return str(records)# 可以被回调的函数放入此字典
available_functions = {"ask_database": ask_database,
}
增加回调事件的响应
from typing_extensions import override
from openai import AssistantEventHandlerclass EventHandler(AssistantEventHandler):@overridedef on_text_created(self, text) -> None:"""响应回复创建事件"""print(f"\nassistant > ", end="", flush=True)@overridedef on_text_delta(self, delta, snapshot):"""响应输出生成的流片段"""print(delta.value, end="", flush=True)@overridedef on_tool_call_created(self, tool_call):"""响应工具调用"""print(f"\nassistant > {tool_call.type}\n", flush=True)@overridedef on_tool_call_delta(self, delta, snapshot):"""响应工具调用的流片段"""if delta.type == 'code_interpreter':if delta.code_interpreter.input:print(delta.code_interpreter.input, end="", flush=True)if delta.code_interpreter.outputs:print(f"\n\noutput >", flush=True)for output in delta.code_interpreter.outputs:if output.type == "logs":print(f"\n{output.logs}", flush=True)@overridedef on_event(self, event):"""响应 'requires_action' 事件"""if event.event == 'thread.run.requires_action':run_id = event.data.id # 获取 run IDself.handle_requires_action(event.data, run_id)def handle_requires_action(self, data, run_id):tool_outputs = []for tool in data.required_action.submit_tool_outputs.tool_calls:arguments = json.loads(tool.function.arguments)print(f"{tool.function.name}({arguments})",flush=True)# 运行 functiontool_outputs.append({"tool_call_id": tool.id,"output": available_functions[tool.function.name](**arguments)})# 提交 function 的结果,并继续运行 runself.submit_tool_outputs(tool_outputs, run_id)def submit_tool_outputs(self, tool_outputs, run_id):"""提交function结果,并继续流"""with client.beta.threads.runs.submit_tool_outputs_stream(thread_id=self.current_run.thread_id,run_id=self.current_run.id,tool_outputs=tool_outputs,event_handler=EventHandler(),) as stream:stream.until_done()
# 创建 thread
thread = client.beta.threads.create()# 添加 user message
message = client.beta.threads.messages.create(thread_id=thread.id,role="user",content="平均一堂课多长时间",
)
# 使用 stream 接口并传入 EventHandler
with client.beta.threads.runs.stream(thread_id=thread.id,assistant_id=assistant_id,event_handler=EventHandler(),
) as stream:stream.until_done()
两个无依赖的 function 会在一次请求中一起被调用
# 创建 thread
thread = client.beta.threads.create()# 添加 user message
message = client.beta.threads.messages.create(thread_id=thread.id,role="user",content="张三上几堂课,比李四多上几堂",
)
# 使用 stream 接口并传入 EventHandler
with client.beta.threads.runs.stream(thread_id=thread.id,assistant_id=assistant_id,event_handler=EventHandler(),
) as stream:stream.until_done()
assistant > functionassistant > functionask_database({'query': "SELECT COUNT(*) AS count FROM Courses WHERE instructor = '张三';"}) ask_database({'query': "SELECT COUNT(*) AS count FROM Courses WHERE instructor = '李四';"})assistant > 张三上了4堂课,而李四上了1堂课。因此,张三比李四多上了3堂课。
更多流中的 Event: https://platform.openai.com/docs/api-reference/assistants-streaming/events
相关文章:

【AI大模型】GPTS 与 Assistants API
前言 2023 年 11 月 6 日,OpenAI DevDay 发表了一系列新能力,其中包括:GPT Store 和 Assistants API。 GPTs 和 Assistants API 本质是降低开发门槛 可操控性和易用性之间的权衡与折中: 更多技术路线选择:原生 API、…...

攻击者开始使用 XLL 文件进行攻击
近期,研究人员发现使用恶意 Microsoft Excel 加载项(XLL)文件发起攻击的行动有所增加,这项技术的 MITRE ATT&CK 技术项编号为 T1137.006。 这些加载项都是为了使用户能够利用高性能函数,为 Excel 工作表提供 API …...

Why RAG is slower than LLM?
I used RAG with LLAMA3 for AI bot. I find RAG with chromadb is much slower than call LLM itself. Following the test result, with just one simple web page about 1000 words, it takes more than 2 seconds for retrieving: 我使用RAG(可能是指某种特定的…...

Word页码设置,封面无页码,目录摘要阿拉伯数字I,II,III页码,正文开始123为页码
一、背景 使用Word写项目书或论文时,需要正确插入页码,比如封面无页码,目录摘要阿拉伯数字I,II,III为页码,正文开始以123为页码,下面介绍具体实施方法。 所用Word版本:2021 二、W…...

汽车汽配图纸管理、产品研发管理解决方案
汽车汽配图纸管理、产品研发管理解决方案 随着全球汽车市场的快速发展,中国汽车汽配行业迎来了前所未有的发展机遇。然而,在这一过程中,企业也面临着诸多挑战,如研发能力的提升、技术资料管理的复杂性、以及跨部门协作的困难等。为…...

小程序简单版音乐播放器
小程序简单版音乐播放器 结构 先来看看页面结构 <!-- wxml --><!-- 标签页标题 --> <view class"tab"><view class"tab-item {{tab0?active:}}" bindtap"changeItem" data-item"0">音乐推荐</view><…...

驾校预约管理系统
摘 要 随着驾驶技术的普及和交通安全意识的增强,越来越多的人选择参加驾校培训,以获取驾驶执照。然而,驾校管理面临着日益增长的学员数量和繁琐的预约管理工作。为了提高驾校的管理效率和服务质量,驾校预约管理系统成为了必不可少…...

C++ 左值右值 || std::move() || 浅拷贝,深拷贝 || 数据类型
数据类型: 作用:决定变量所占内存空间的字节大小,和布局方式基本数据类型: 算数类型: 整形(bool / char……扩展集 / int / long……)&& 浮点形(float/double……ÿ…...

发那科机器人IO 分配
IO 信号 也称为输入\输出信号,是机器人与外围设备通信的电信号...

ubuntu开机怎么进入、退出命令行界面
要在Ubuntu系统开机时进入命令行界面,可以按照以下步骤操作: 在开机过程中按下Ctrl Alt F1组合键,这将会切换到第一个虚拟控制台,即命令行界面。如果Ctrl Alt F1没有生效,也可以尝试Ctrl Alt F2、Ctrl Alt F3…...

『FPGA通信接口』LVDS接口(4)LVDS接收端设计
文章目录 1.LVDS接收端概述2逻辑框图3.xapp855训练代码解读4.接收端发送端联调5.传送门 1.LVDS接收端概述 接收端的传输模型各个属性应该与LVDS发送端各属性一致,例如,如果用于接收CMOS图像传感器的图像数据,则接收端程序的串化因子、通道个…...

面试题:HTTP的body是二进制还是文本
实际上,HTTP的body可以是二进制数据,也可以是文本。HTTP协议本身不对body内容的格式做限制,具体格式取决于Content-Type头字段的定义。 文本数据: 当Content-Type头字段指定为文本类型时(如text/plain、text/html、ap…...

5分钟带你部署一套Jenkins持续集成环境
5分钟带你部署一套Jenkins持续集成环境 Jenkins是开源CI&CD软件领导者, 提供超过1000个插件来支持构建、部署、自动化, 满足任何项目的需要。 Jenkins的优点 持续集成和持续交付 作为一个可扩展的自动化服务器,Jenkins 可以用作简单的 CI…...

OpenAI突然宣布停止向中国提供API服务!
标题 🌟 OpenAI突然宣布停止向中国提供API服务! 🌟摘要 📜引言 📢正文 📝1. OpenAI API的重要性2. 停止服务的原因分析3. 对中国市场的影响4. 应对措施代码案例 📂常见问题解答(QA)❓…...

Bootstrap 标签
Bootstrap 标签 引言 Bootstrap 是一个流行的前端框架,它提供了一套丰富的组件和工具,帮助开发者快速构建响应式和移动优先的网页。在 Bootstrap 中,标签(Badge)是一种小巧的组件,用于显示计数、提示或标…...

EtherCAT主站SOEM -- 37 -- win-soem-win10及win11系统QT-SOEM-1个电机转圈圈-周期同步速度模式(CSV模式)
EtherCAT主站SOEM -- 37 -- win-soem-win10及win11系统QT-SOEM-1个电机转圈圈-周期同步速度模式(CSV模式) 0 QT-SOEM及STM32F767-SOEM视频欣赏及源代码链接:0.1 Linux--Ubuntu系统之 QT-SOEM博客、视频欣赏及源代码链接0.2 STM32F767-SOEM 博客、视频欣赏及源代码链接0.3 wi…...

老板舍不得买库存管理软件❓一招解决
在当今快节奏的商业环境中,仓库管理是企业运作中不可或缺的一环。对于许多中小型企业而言,简易且高效的库存管理系统尤为重要。搭贝简易库存管理系统针对仓库的出入库进行有效管理,帮助企业实现库存的透明化和流程的自动化。 客户的痛点 1. …...

【MySQL数据库】:MySQL视图特性
目录 视图的概念 基本使用 准备测试表 创建视图 修改视图影响基表 修改基表影响视图 删除视图 视图规则和限制 视图的概念 视图是一个虚拟表,其内容由查询定义,同真实的表一样,视图包含一系列带有名称的列和行数据。视图中的数据…...

malloc、free和new delete的区别
malloc/free 和 new/delete 是在 C 中分配和释放内存的两种不同方法。它们主要有以下区别: 1. 语法和用法 malloc 和 free: malloc开辟空间时需要手动计算分配的空间大小 int* p (int*)malloc(sizeof(int) * 10); // 分配10个int类型的内存 // 使用内存 free(p); …...

如何有效地优化 Erlang 程序的内存使用,以应对大规模数据处理的需求?
要有效地优化Erlang程序的内存使用,以应对大规模数据处理的需求,可以考虑以下几个方面: 减少不必要的内存分配:避免过多的数据复制和不必要的数据结构创建。可以使用Erlang的二进制数据类型来避免数据复制,使用原子数据…...

vue3项目使用@antv/g6实现可视化流程功能
文章目录 项目需求一、需要解决的问题二、初步使用1.动态数据-组件封装(解决拖拽会留下痕迹的问题,引用图片,在节点右上角渲染图标,实现,事现旋转动画,达到loading效果)2.文本太长,超出部分显示(...),如下函…...

【Linux网络(一)初识计算机网络】
一、网络发展 1.发展背景 2.发展类型 二、网络协议 1.认识协议 2.协议分层 3.OSI七层模型 4.TCP/IP协议 三、网络传输 1.协议报头 2.局域网内的两台主机通信 3.跨网络的两台主机通信 四、网络地址 1.IP地址 2.MAC地址 一、网络发展 1.发展背景 计算机网络的发展…...

Vulhub——Log4j、solr
文章目录 一、Log4j1.1 Apache Log4j2 lookup JNDI 注入漏洞(CVE-2021-44228)1.2 Apache Log4j Server 反序列化命令执行漏洞(CVE-2017-5645) 二、Solr2.1 Apache Solr 远程命令执行漏洞(CVE-2017-12629)2.…...

linux 设置程序自启动
程序随系统开机自启动的方法有很多种, 这里介绍一种简单且常用的, 通过系统的systemd服务进行自启动。 第一步: 新建一个.service文件 sudo vim /etc/systemd/system/myservice.service[Unit] DescriptionMy Service #Afternetwork.target[…...

PostgreSQL 分区表与并行查询(十)
1. 分区表概述 1.1 什么是分区表 分区表是将大表分割成更小、更可管理的部分的技术。每个分区表都可以单独进行索引和查询,从而提高查询性能和管理效率。 1.2 分区策略 1.2.1 基于范围的分区 按照时间范围或者数值范围进行分区,如按月或按地区。 C…...

React Hooks使用规则:为什么不在条件语句和循环中使用它们
React Hooks为函数组件引入了状态和生命周期特性,极大地增强了其功能。然而,正确使用Hooks是确保组件稳定性和性能的关键。本文将探讨React Hooks的基本规则,以及为什么我们不应该在条件语句和循环中使用它们。 Hooks的基本规则 React团队为…...

【Docker】Consul 和API
目录 一、Consul 1. 拉取镜像 2. 启动第一个consul服务:consul1 3. 查看consul service1 的ip地址 4. 启动第二个consul服务:consul2, 并加入consul1(使用join命令) 5. 启动第三个consul服务:consul3&…...

Python polars学习-07 缺失值
背景 polars学习系列文章,第7篇 缺失值 该系列文章会分享到github,大家可以去下载jupyter文件,进行参考学习 仓库地址:https://github.com/DataShare-duo/polars_learn 小编运行环境 import sysprint(python 版本:…...

前端面试题(八)答案版
面试形式:线下面试:一面:30分钟二面:30分钟 特殊要求:内网开发自研UI组件库(无文档介绍)学习能力要求高 面试评价:题目灵活应用性较强 面试官:项目负责人前端负责人 …...

在交易中出场比入场更为重要
出场策略和交易退出机制比交易者入场的方式更为关键,它们对整体回报和结果的持续性有着更大的影响。 即使交易者入场时的条件并非最佳,良好的出场策略也能扭转局势。反之,即使交易者以近乎完美的条件入场,若出场策略管理不当&…...