TaskWeaver使用记录

news2025/1/14 18:08:07

TaskWeaver使用记录

  • 1. 基本介绍
  • 2. 总体结构与流程
  • 3. 概念细节
    • 3.1 Project
    • 3.2 Session
    • 3.3 Memory
    • 3.4 Conversation
    • 3.5 Round
    • 3.6 Post
    • 3.7 Attachment
    • 3.8 Plugin
    • 3.9 Executor
  • 4. 代码特点
  • 5. 使用过程
    • 5.1 api调用
    • 5.2 本地模型使用
    • 5.3 添加插件
  • 6. 存在的问题与使用体验
    • 6.1 判别模型以提供给planner不同的prompt
    • 6.2 缓存prompt
    • 6.3 判断会话是否结束
    • 6.3 executor的结果直接反馈给用户
    • 6.4 陷入死循环的问题
    • 6.4 额外的角色专门与用户进行交互
    • 6.5 用户介入流程copilot
  • 7. 总结

1. 基本介绍

本文记录一下taskweaver项目的使用过程,其中遇到的问题,以及带来的启发。
Taskweaver是最近比较火的一个AI Agent项目,由微软开发,目前在git上已经有4.6k Star。

项目地址:https://github.com/microsoft/TaskWeaver
论文地址:https://export.arxiv.org/pdf/2311.17541
说明文档:https://microsoft.github.io/TaskWeaver/docs/overview

Taskweaver的特点是,能够按照用户的指示,自动生成并执行代码,以完成一些更复杂的任务。在执行过程中,不仅保留了对话历史,还将代码执行的结果(包括报错信息)保留下来,以便解决代码执行过程中的问题。

2. 总体结构与流程

下面引用的是Taskweaver的结构图:

taskweaver

从图中可以看出,Taskweaver主要由两部分构成,Planer和Code Interpreter,其中Code Interpreter又由负责生成代码的Code Generator和负责执行代码的Code Executor构成。

从执行的流程上来看,可以大致划分为以下几个过程:

  • (1)用户发出指令,Planer接收到用户的指令。
  • (2)Planer根据用户的指令,结合prompt中的例子,做出初始计划(init plan)。
  • (3)Planer将init plan转化为更加精简的最终计划(final plan),计划中的每一步可以看作是一个子任务。
  • (4)逐步将计划中的每一步发送给Code Interpreter。
  • (5)Code Generator根据接收到的任务,从可用的插件里进行选择,并生成一段用于完成当前步骤的代码,发送给Code Executor。
  • (6)Code Executor执行代码,并将执行结果反馈给Planer。
  • (7)反复执行4-6,直到所有步骤都已经执行完成。Planer将结果返回给用户。
  • (8)用户可以继续发出新的指令。

在论文的附录A中,给出了具体的例子:
case study

3. 概念细节

在Taskweaver中,涉及到很多概念,在这里进行汇总介绍。

3.1 Project

项目可以看作是taskweaver中最高层级的概念,每个项目会指定一个特定的目录,其中包含了指导planer的prompt和example,项目下的每个会话(Session)的日志,项目中可以使用的各类插件,以及使用的LLM相关的配置。

基于每个项目可以多次创建会话。

3.2 Session

会话是实际代码执行中比较高层级,独立且完整的概念了,各种角色、组件都是挂在具体的会话下,每次启动taskweaver,就视作是唤起了一次会话。

3.3 Memory

Memory相当于是对话历史plus,除了像一般的LLM项目中,将对话历史保存下来,memory还保留了Code Executor的执行结果,并且在保留记忆的时候,利用compression组件对对话的内容进行了总结。

在代码结构中,Memory作为Session的一个属性。

3.4 Conversation

有点反常识的是,对话是Memory的一个属性,memory保存着所有的对话过程。而对话中记录的是taskweaver系统与用户交互的过程,每个对话由若干轮次(Round)构成。

3.5 Round

Round是conversation中的基础单元,每个round可以看作是post的集合。在round中记录着当前轮次的状态。

3.6 Post

Post是在不同角色之间传递的消息,这些角色包括用户,Planer,Code Generator,以及Code Executor,记录了从哪个角色发送到哪个角色,以及消息的内容和附件(Attachment)。

3.7 Attachment

Attachment是在Post中,除了一般的文本信息之外,需要特殊被标记出来的附件,包括code,markdown,execution_result等,不同的角色通过判断特定的attachment的类型和其中的内容,来采取进一步的行动。

3.8 Plugin

插件是在代码生成过程中,提供给Code Generator的,用于完成某些相对复杂的任务。在提供插件的时候,需要提供两个文件,其一是py脚本,一旦插件被选中,脚本会被提供给Code Executor用于执行;其二是yaml文件,用于添加到Code Generator的prompt部分中,其中提供了该插件的介绍,使用例子,以及输入输出的类型等信息。

在执行的时候,Code Generator有两种模式选择可用的Plugin。

  • 默认全部可用,yaml文件中的enabled设置为true的全部plugin都会被加载。
  • 使用相似度判断,使用LLM Service中的embedding服务对plugin的desc和当前的需要执行的步骤分别进行编码,然后根据相似度取topk。

3.9 Executor

Code Generator所生成的代码会交给Code Executor执行,这样就要求Executor具备python运行环境。Executor使用执行代码有两种方法,docker容器和jupyter kernel。在默认的配置中,使用的docker container,但是我实际操作过程中,会出现报错,可能是环境配置的缘故。所以在environment.py中,将mode写成EnvMode.Local,于是可以运行。

但是需要注意的是,Local模式的原理是利用ipykernel模块创建jupyter内核,这样的运行环境是与启用taskweaver的python环境是一致的,这样并不安全,也不灵活,这也是为什么taskweaver并不建议使用这种模式。

考虑到Code Generator所生成的代码中,包含try import; execept pip install 之类的语句,这样的作法可能会改变基础python环境,所以我在实验过程中,将各种prompt和example中与pip install语句相关的部分都删除。

如果需要在不同的环境中运行代码,可以在plugin中添加自定义组件,并且在组件中访问其他环境所创建的api。

4. 代码特点

作为一个相当完备的项目,taskweaver的代码注释比较清晰,但是由于加入了各种工程化的部分,导致代码读起来并不轻松,如果做实验的话会比较麻烦,尤其是引入了类似JAVA各种框架中的inject机制,在逐步debug的时候非常不方便。

  • 从代码结构来看,项目代码中,taskweaver目录下是源码部分。

  • project目录中是当前的项目信息,项目可用的插件文件,Planer的example,执行的日志等。
    命令行启动一个TaskWeaverApp时,需要指定具体的项目目录。

  • playground中提供了web界面。

另外,这个工程在运行的过程中,受到@tracing_decorator的影响,导致报错(装饰器内报错)在打印之前,并不能够像一般的程序一样,将所有print的信息打印出来,使得debug更费劲了。一个小技巧是将print改成raise,将需要打印的内容当作错误抛出,就可以看到打印的内容了。

5. 使用过程

这一部分记录一下使用taskweaver过程中遇到的一些问题。

5.1 api调用

首先是关于大模型的使用,taskweaver提供了若干种模型的调用方法,包括openai,qwen等接口的使用。通过配置API KEY可以轻松的使用这些大模型。

然而直接使用api也存在一些问题。由于访问频率以及输入prompt长度的原因(taskweaver的planer和code generator本身的prompt就很长,拼接上各种example、experience、plugin之后就会变得非常长),很容易导致大模型接口调用失败,而如果使用长文本的接口服务,则费用就会很高。

5.2 本地模型使用

如果要使用本地模型,则需要在taskweaver.llm的目录下增加一个自己的py文件,可以仿照qwen.py实现,需要保证chat_completion返回的一个Generator,其中的内容形式如下即可:

{"status_code": 200, "request_id": "226ff7aa-b675-98d0-adab-6e5b98c79250", "code": "", "message": "", "output": {"text": null, "finish_reason": null, "choices": [{"finish_reason": "null", "message": {"role": "assistant", "content": "你好"}}]}, "usage": {"input_tokens": 20, "output_tokens": 1, "total_tokens": 21}}
{"status_code": 200, "request_id": "226ff7aa-b675-98d0-adab-6e5b98c79250", "code": "", "message": "", "output": {"text": null, "finish_reason": null, "choices": [{"finish_reason": "null", "message": {"role": "assistant", "content": "!"}}]}, "usage": {"input_tokens": 20, "output_tokens": 2, "total_tokens": 22}}
{"status_code": 200, "request_id": "226ff7aa-b675-98d0-adab-6e5b98c79250", "code": "", "message": "", "output": {"text": null, "finish_reason": null, "choices": [{"finish_reason": "null", "message": {"role": "assistant", "content": "有什么"}}]}, "usage": {"input_tokens": 20, "output_tokens": 3, "total_tokens": 23}}
{"status_code": 200, "request_id": "226ff7aa-b675-98d0-adab-6e5b98c79250", "code": "", "message": "", "output": {"text": null, "finish_reason": null, "choices": [{"finish_reason": "null", "message": {"role": "assistant", "content": "我能帮助你的吗?"}}]}, "usage": {"input_tokens": 20, "output_tokens": 8, "total_tokens": 28}}
{"status_code": 200, "request_id": "226ff7aa-b675-98d0-adab-6e5b98c79250", "code": "", "message": "", "output": {"text": null, "finish_reason": null, "choices": [{"finish_reason": "null", "message": {"role": "assistant", "content": ""}}]}, "usage": {"input_tokens": 20, "output_tokens": 8, "total_tokens": 28}}
{"status_code": 200, "request_id": "226ff7aa-b675-98d0-adab-6e5b98c79250", "code": "", "message": "", "output": {"text": null, "finish_reason": null, "choices": [{"finish_reason": "stop", "message": {"role": "assistant", "content": ""}}]}, "usage": {"input_tokens": 20, "output_tokens": 8, "total_tokens": 28}}

然后编辑taskweaver.llm.init.py,在构造方法中加入自己本地的api_type。

5.3 添加插件

在前文的介绍中提到了,插件的作用是为了实现某些特定场景的功能,完成code generator无法实现的一些复杂任务。默认提供的插件包括:pdf文档阅读,图像转文本,语音识别文本,讲笑话等。

添加自定义插件的方法也不复杂,在project.plugins目中,照葫芦画瓢地加入一个py文件和一个yaml文件即可。

  • 在py文件中,可以通过调用其他外部接口的方法,来使用其他环境。
  • 在yaml中,需要将enabled设置为true,否则这个插件将不会被加载。

6. 存在的问题与使用体验

最后记录一下我在试用taskweaver过程中的感受,以及个人认为可以优化的方向。

6.1 判别模型以提供给planner不同的prompt

目前版本的taskweaver,所有的对话场景,使用的planner都是同样的,我们可以通过planner_prompt.yaml来查看它的prompt:

  ### Examples of planning process
  [Example 1]
  User: count rows for ./data.csv
  init_plan:
  1. Read ./data.csv file 
  2. Count the rows of the loaded data <sequential depend on 1>
  plan:
  1. Read ./data.csv file and count the rows of the loaded data
  
  [Example 2]
  User: Read a manual file and follow the instructions in it.
  init_plan:
  1. Read the file content and show its content to the user
  2. Follow the instructions based on the file content.  <interactively depends on 1>
  plan:
  1. Read the file content and show its content to the user
  2. follow the instructions based on the file content.
  
  [Example 3]
  User: detect anomaly on ./data.csv
  init_plan:
  1. Read the ./data.csv and show me the top 5 rows to understand the data schema 
  2. Confirm the columns to be detected anomalies  <sequentially depends on 1>
  3. Detect anomalies on the loaded data <interactively depends on 2>
  4. Report the detected anomalies to the user <interactively depends on 3>
  plan:
  1. Read the ./data.csv and show me the top 5 rows to understand the data schema and confirm the columns to be detected anomalies
  2. Detect anomalies on the loaded data
  3. Report the detected anomalies to the user
  
  [Example 4]
  User: read a.csv and b.csv and join them together
  init_plan:
  1. Load a.csv as dataframe and show me the top 5 rows to understand the data schema
  2. Load b.csv as dataframe and show me the top 5 rows to understand the data schema 
  3. Ask which column to join <sequentially depends on 1, 2>
  4. Join the two dataframes <interactively depends on 3>
  5. report the result to the user <interactively depends on 4>
  plan:
  1. Load a.csv and b.csv as dataframes, show me the top 5 rows to understand the data schema, and ask which column to join
  2. Join the two dataframes
  3. report the result to the user

可以看到这其中的例子,都是读取数据相关的,所以planner能够针对taskweaver中给出的例子很好地制定计划就一点也不例外了。但是可以预料地是,当用户的指令与数据处理相关的任务没有什么关联的时候,这些prompt就没有什么价值了。

所以很自然地可以想到一个优化的点就是在对话开始之前,将用户query经过一个判别模型进行判断,分类到预设的若干任务种类之中,再根据任务的种类,加载不同的prompt,来创建相应的planner。

6.2 缓存prompt

在使用taskweaver的过程中,一个很直观的感受是,生成的效率很慢,并且随着生成的进行,效率越来越慢。

考虑调用LLM时,拼接出来的prompt除了初始的prompt本身就很长,还要拼接上各种example、experience、plugin、chat_history,这导致在启动对话的时候,需要很大的计算量,来计算prompt部分。

而prompt部分,很大程度上是很固定的(初始的prompt本身),而调用的LLM也是固定的,可以考虑采用kv cache的策略,提前将这部分算好保存下来,从而避免每次都计算。

至于plugin有没有必要提前缓存下来,然后根据被选中的情况,与初始prompt的cache进行拼接,可能需要具体实验一下才能下结论,而且如果这样改造的话,工程量更大一些。

6.3 判断会话是否结束

Taskweaver中,为了防止会话历史过长导致的计算资源开销过大,采用了Memory管理机制,利用叫RoundCompressor的组件来对对话历史进行总结压缩。但是好像并没有在用户给出新的query时,判断新的query与之前的对话历史是否相关。这里也可以添加一个判断机制,如果新的query与之前的内容完全无关时,就清除之前的所有对话历史。

6.3 executor的结果直接反馈给用户

从Taskweaver的示意图可以看出,每当Code Executor执行完代码,并不会将结果直接反馈给用户,而是将执行结果给到Planner,由Planner重新组织之后,再给到用户,在这个过程中可能存在信息的偏差,并且由Planner重新组织一遍语言,会更加耗时。

例如,我提供了一个plugin,其内容是实体识别。我输入的指令是:“识别这段话中存在的实体:xxxxxxx”。
Code Executor给出的结果是:

{'entity_id': 'Q23792', 'entity_mentions': [{'end_pos': 57, 'entity_mention_id': '2', 'entity_type': 'LOC', 'mention_type': 'NAM', 'nid': 'Q23792', 'start_pos': 50, 'words': '巴勒斯坦加沙地带'}], 'entity_type': 'LOC'}
{'entity_id': 'Q974850', 'entity_mentions': [{'end_pos': 117, 'entity_mention_id': '9', 'entity_type': 'WEA', 'mention_type': 'NOM', 'nid': 'Q974850', 'start_pos': 116, 'words': '导弹'}], 'entity_type': 'WEA'}
{'entity_id': 'Q484000', 'entity_mentions': [{'end_pos': 121, 'entity_mention_id': '10', 'entity_type': 'WEA', 'mention_type': 'NOM', 'nid': 'Q484000', 'start_pos': 119, 'words': '无人机'}], 'entity_type': 'WEA'}
{'entity_id': 'Q6840712', 'entity_mentions': [{'end_pos': 132, 'entity_mention_id': '12', 'entity_type': 'LOC', 'mention_type': 'NAM', 'nid': 'Q6840712', 'start_pos': 129, 'words': '中东地区'}], 'entity_type': 'LOC'}
{'entity_id': 'Q41053', 'entity_mentions': [{'end_pos': 141, 'entity_mention_id': '13', 'entity_type': 'ORG', 'mention_type': 'NAM', 'nid': 'Q41053', 'start_pos': 136, 'words': '黎巴嫩真主党'}], 'entity_type': 'ORG'}
{'entity_id': 'Q516655', 'entity_mentions': [{'end_pos': 148, 'entity_mention_id': '14', 'entity_type': 'ORG', 'mention_type': 'NAM', 'nid': 'Q516655', 'start_pos': 143, 'words': '也门胡塞武装'}], 'entity_type': 'ORG'}
 ......

而经过Planner的一顿操作之后,最终输出给用户的结果变成了:

The entities recognized in the text are as follows:

1. **Iran** (GPE): mentioned 3 times - at positions 63-64, 70-71, and 126-127
2. **Israel** (GPE): mentioned 3 times - at positions 12-14, 81-83, and 108-110
3. **Palestinian Gaza Strip** (LOC): mentioned once at position 50-57
4. **Missile** (WEA): mentioned once at position 116-117
5. **Unmanned Aerial Vehicle (UAV)** (WEA): mentioned once at position 119-121
6. **Middle East** (LOC): mentioned once at position 129-132
7. **Lebanese Hezbollah** (ORG): mentioned once at position 136-141
8. **Houthi Militia in Yemen** (ORG): mentioned once at position 143-148
9. **Islamic Revolutionary Guard Corps of Iran** (ORG): mentioned once at position 91-99

These entities represent geographical locations (GPE), weapons (WEA), regions (LOC), and organizations (ORG) mentioned in the text.

可以看出模型做了一些不必要的总结,并且因为Planner的prompt整体是英文的,它还把结果给翻译了。

并且只有当Planner指定的计划中,执行到当前计划是“ Report to the user.”时,才会将内容输出给用户,否则会反复调用Code Generator和Executor。这就很容易造成循环,即便没有陷入循环,也会消耗大量时间。

因此在某些特定的情况下,最好保留一个通路,直接将Executor的结果输出给用户。

6.4 陷入死循环的问题

Taskweaver关注的更多的是代码能够安全的执行,每次代码执行失败时,就会将报错的结果与代码一并返回给Code Generator进行修改,然后再将修改过后的代码,再交给Code Executor尝试执行。而当LLM能力不足,或用户本身的需求不合理时,很容在这个过程中陷入死循环,因此需要设置一个出口,在适当的时候跳出。

6.4 额外的角色专门与用户进行交互

Taskweaver对自身的定位是一个可以执行代码的agent,这其中就涉及到,它的作用更倾向于执行,但是也需要适当地对用户的指令给出文字性的回应。于是taskweaver给出的方案是将代码执行的结果,给planner,让它梳理一下,再给到用户。

但这样就带来了一个问题,planner的prompt是用来制定计划的,所以这里可以考虑添加另一个额外的角色,专门用来总结Code Interpreter的输出结果。

6.5 用户介入流程copilot

7. 总结

个人感觉,Taskweaver是一个很优秀的项目,在各种执行逻辑上写的很完备,但是也正是因为太完备了,导致改造这个代码难度很大。相比在这个基础上改造,我还是更倾向于参照它的思路,从头开发一套类似的agent系统。当然,也期待TaskWeaver后续的更新。

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

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

相关文章

C语言 | Leetcode C语言题解之第40题组合总和II

题目&#xff1a; 题解&#xff1a; int** ans; int* ansColumnSizes; int ansSize;int* sequence; int sequenceSize;int** freq; int freqSize;void dfs(int pos, int rest) {if (rest 0) {int* tmp malloc(sizeof(int) * sequenceSize);memcpy(tmp, sequence, sizeof(int…

Web前端 JavaScript笔记7

js的执行机制 js是单线程 同步&#xff1a;前面一个任务执行结束之后&#xff0c;执行后一个 异步&#xff1a;异步任务&#xff0c;引擎放在一边&#xff0c;不进入主线程&#xff0c;而进入任务队列的任务 js通过浏览器解析&#xff0c;浏览器靠引擎解析 回调函数同步任务执行…

锂电池寿命预测 | Matlab基于GRU门控循环单元的锂电池寿命预测

目录 预测效果基本介绍程序设计参考资料 预测效果 基本介绍 锂电池寿命预测 | Matlab基于GRU门控循环单元的锂电池寿命预测 Matlab基于GRU的锂电池剩余寿命预测 基于GRU的锂电池剩余寿命预测&#xff08;单变量&#xff09; 运行环境Matlab2020及以上 锂电池的剩余寿命预测是…

探索早期投资的奥秘:符文(Runes)生态系统的崛起

随着加密市场的迅速发展&#xff0c;投资者们对早期项目的关注越来越高。在这个充满变数和机遇的领域里&#xff0c;抢占先机意味着可能获得巨大的回报。符文&#xff08;Runes&#xff09;生态系统作为近期备受瞩目的项目之一&#xff0c;引发了众多投资者的兴趣。本文将深入探…

Java数据结构-二叉树

目录 1. 树与二叉树1.1 树1.2 二叉树1.3 树的相关概念1.4 特殊的二叉树1.5 二叉树性质1.6 二叉树的存储与表示方法 2. 二叉树遍历2.1 前序遍历2.2 中序遍历2.3 后序遍历2.4 层序遍历 3. 二叉树基本操作3.1 求树的所有结点个数3.2 求叶子结点个数3.3 求第k层结点个数3.4 求二叉树…

笔记-----BFS宽度优先搜索

对于BFS&#xff1a;宽搜第一次搜到就是最小值&#xff0c;并且基于迭代&#xff0c;不会爆栈。 Flood Fill 模型 如果直译的话就是&#xff1a;洪水覆盖&#xff0c;意思就是像是从一个点一圈圈的往外扩散&#xff0c;如果遇见能够连通的就扩散&#xff0c;如果遇见无法联通的…

医院的工作手机、平板等智能终端的安全管理

移动互联网的时代&#xff0c;在医疗行业&#xff0c;特别是各级省市的医院&#xff0c;在各个科室的日常办公及业务开展都依赖计算机及智能终端设备如平板、手机等&#xff0c;这样能提高医务人员的办公效率&#xff0c;从而更好的为患者服务。 在医院信息化发展过程中&#…

vue中使用水印

1. 在utils下创建watermark.js const watermark {}/**** param {要设置的水印的内容} str* param {需要设置水印的容器} container* param {需要设置水印的每一块的宽度} canWidth* param {需要设置水印的每一块的高度} canHeight* param {需要设置水印的字体} canFont* para…

line 1:20 no viable alternative at input ‘point,‘

背景 遇到一个蛋疼的问题&#xff0c;搞得老夫难受的一&#xff0c;解决了索性记录下 Creating a new SqlSession SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession61b0005f] was not registered for synchronization because synchronization is not activ…

C# 报输入字符串格式不正确的原因

先放错误代码 23 class Voicewater 24 { 25 public void voicealarm(int tem) 26 { 27 Console.WriteLine("现在的温度是{}度了",tem); 28 } 29 } 解决方法…

盲人盲杖:科技革新,助力视障人士独立出行

在我们的社会中&#xff0c;盲人朋友们以其坚韧的精神风貌&#xff0c;生动诠释着生活的多样与可能。然而&#xff0c;当我们聚焦于他们的日常出行&#xff0c;那些普通人视为寻常的街道、路口&#xff0c;却成为他们必须面对的严峻挑战。如何切实提升盲人盲杖的功能&#xff0…

PostgreSql-Install

PostgreSql源码安装 一、源代码下载二、操作系统配置三、编译安装四、启动数据库五、相关命令 PostgreSQL是一个强大的 开源对象关系数据库系统&#xff0c;它使用并扩展了SQL语言&#xff0c;并结合了许多功能&#xff0c;可以安全地存储和扩展最复杂的数据工作负载。 一、源…

【C语言】指针详解(五)

目录 1.字符指针 1.1常量字符串 2.指针数组 3.数组指针 1.字符指针 字符指针就是指向字符的指针&#xff0c;字符指针可以存储字符变量的地址。 举例如下&#xff1a; 定义指针变量pa存a的地址&#xff0c;改变*pa的值&#xff0c;a也会随之改变 。 1.1常量字符串 &#x1f…

开发工具——postman使用教程详解

一、概念 1、Postman是一款功能强大的网页调试与发送网页HTTP请求的Chrome插件&#xff0c;Postman分为Postman native app和Postman Chrome app两个版本。目前Chrome app已停止维护&#xff0c;官方不推荐使用该版本。 2、官网下载地址&#xff1a;http://www.getpostman.com…

MATLAB实现禁忌搜索算法优化柔性车间调度fjsp

禁忌搜索算法的流程可以归纳为以下几个步骤&#xff1a; 初始化&#xff1a; 利用贪婪算法或其他局部搜索算法生成一个初始解。清空禁忌表。设置禁忌长度&#xff08;即禁忌表中禁止操作的期限&#xff09;。邻域搜索产生候选解&#xff1a; 通过特定的搜索算子&#xff08;如…

微信小程序地图polyline坐标太多异常显示BUG

描述 微信小程序map地图上显示polyline线&#xff0c;点位超过1250个出现bug&#xff0c;&#xff08;仅真机上出现&#xff0c;模拟器上正常&#xff09; 这里以加载四川省边界为例, 以下是示例代码 // 读取geojson数据 uni.request({url: https://geo.datav.aliyun.com/a…

用 element ui 实现季度选择器

由于在数据项目中经常以各种时间条件查询数据&#xff0c;所以时间选择器&#xff08;DatePicker&#xff09;组件是很常用的组件。但是在我使用的 Element UI 中&#xff0c;缺少了季度选择器的功能。 简易实现 一开始我根据时间范围使用 select 去遍历,如 2024-Q1、2023-Q4…

Node.js 基础学习

文章目录 1. Node.js1.1 是什么&#xff1f;1.2 作用 2. 命令行工具2.1 命令的结构2.2 常用命令 3. Node.js 注意点3.1 Node.js 中不能使用DOM 和BOM 的API3.2 Node.js 中顶级对象叫做global 4. Buffer4.1 Buffer 特点4.2 Buffer 创建方式4.3 Buffer 操作与注意点 5. 计算机基础…

Rust入门-引用借用

一、引用借用&#xff0c;是什么、为什么、怎么用 所有权上篇我们已经讨论过了&#xff0c;所以这篇我们讨论Rust的引用借用 1、引用借用 是什么&#xff1f; Rust 通过借用(Borrowing) 这个概念来达成上述的目的&#xff0c;获取变量的引用&#xff0c;称之为借用(borrowin…

CERLAB无人机自主框架: 1-环境搭建

前言&#xff1a;更多更新文章详见我的个人博客主页【MGodmonkeyの世界】 描述&#xff1a;欢迎来到CERLAB无人机自主框架&#xff0c;这是一个用于自主无人飞行器 (UAV) 的多功能模块化框架。该框架包括不同的组件 (模拟器&#xff0c;感知&#xff0c;映射&#xff0c;规划和…