当前位置: 首页 > news >正文

如何用 LangChain 实现一个Zero Shot智能决策器(附源码)

写在前面

最近一直在研究Agent和Tool的使用,今天给大家带来一篇何枝大佬(知乎@何枝)的文章《如何用LangChain实现一个Zero Shot智能决策器》,并附上源码。

知乎:https://zhuanlan.zhihu.com/p/627333499

LangChain是当下非常热门的一个库,其通过融合LLM的强大能力能够让我们快速地搭建一个具备 “思考能力” 的AI助手。在今天的文章中,我们将侧重于讲解:LangChain是如何进行自我思考并做出决策的。

Github:https://github.com/hwchase17/langchain
官方文档:LangChain 0.0.160

假设今天我们有一个朋友过生日,你很头疼,你不知道送什么礼物给他。这时候,你希望有一个机器人能告诉你一些推荐,如何实现这样一个机器人呢?

1. 人在分析问题时候的思维

如果今天需要你自己去思考送什么礼物,你可能会这么想:

  • 我这个朋友是女生。
  • 女生可能会喜欢一些口红、护肤品等等。
  • 好!那我就送她一只口红吧!

可以看出,人们在得到一个问题的最终答案前,通常是会有若干个「中间步骤(intermediate steps)」,LangChain 也是这样!在人们给出一个问题后,LangChain会引导LLM进行一步一步的分析,最终得到一个确定的答案。

下面,我们就将使用 LangChain + ChatGPT 来复现上述的思考步骤。当我们问两个不同的朋友时,模型会给出不同的推荐礼物:

朋友1

  • User:帮我推荐几个送给小红的礼物
  • Model:为小红推荐的礼物有:夏季碎花裙、轻盈帆布包、琉璃唇釉。

朋友2

  • User:我想送点礼物给张三
  • Model:根据张三的性别和兴趣,我可以推荐Steam爆款、RTX-3090或iPhone 14作为礼物。

2. 思维链中的工具设计

我们先分析一下,上述思维链中一共需要两个功能:

  • 找出人物的性别(张三是男的,小红是女生)
  • 根据人物的性别推荐对应的商品(男生喜欢数码产品,女生喜欢化妆品)

尽管LLM本身就存在一定的性别推理、商品推荐的能力,但为了更好的利用本地的数据,LangChain 提供了Tool类,能够更方便我们使用本地数据,以便于更好的对齐业务需求。图片

我们可以通过以下方式来定义这两个工具:

from langchain.agents import Tooldef find_gender(name: str):"""模拟本地数据库查询。Args:name (str): 人物名称,由LLM提取。Returns:_type_: _description_"""info = {                     # 模拟数据库,存放人物对应的性别'张三': '男','小红': '女'}return info.get(name, f'未找到{name}的性别信息,我应该直接返回 Observation: 未知')tool_of_find_gender = Tool(name = "查询人物性别",                         # 工具的名称func=find_gender,                            # 工具的实现函数description="通过人名查找该人物的性别时用的工具,输入应该是人物的名字"   # 【重要】描述工具的用途,LLM 会根据描述来决定是否使用这个工具
)def recommend_item(gender: str):"""根据人物性别推荐不同的商品。Args:gender (str): 人物的性别,由 LLM 提取。Returns:_type_: _description_"""recommend = {'男': ['Steam爆款', 'RTX-9090', 'iPhone 80'],'女': ['夏季碎花裙', '轻盈帆布包', '琉璃唇釉'],'未知': ['AJ新品', '手冲咖啡']}return recommend.get(gender, f'未找到合适的推荐商品,我应该返回 Final Answer: 随便买些什么吧,只要消费就能快乐!')tool_of_recommend_item = Tool(name = "根据性别推荐商品",func=recommend_item,description="当知道了一个人性别后想进一步获得他可能感兴趣的商品时用的工具,输入应该是人物的性别"
)

其中,description和name非常重要,这将帮助LLM参考在何时应该调用这个工具。

3. 思维链的 Prompt 设计

在有了工具后,我们就要正式开始引导模型进行分析了。

首先我们定义整个 prompt 模板:

"""
按照给定的格式回答以下问题。
你可以使用下面这些工具:{tools}回答时需要遵循以下用---括起来的格式:---
Question: 我需要回答的问题
Thought: 回答这个上述我需要做些什么
Action: ”{tool_names}“ 中的其中一个工具名
Action Input: 选择工具所需要的输入
Observation: 选择工具返回的结果
...(这个思考/行动/行动输入/观察可以重复N次)
Thought: 我现在知道最终答案
Final Answer: 原始输入问题的最终答案
---现在开始回答,记得在给出最终答案前多按照指定格式进行一步一步的推理。Question: {input}
{agent_scratchpad}
"""

这个模版中,最重要的是:

  • Thought
  • Action
  • Action Input

这3个部分是AI在思维链中进行自我思考的过程,我们可以直观来看看 LLM 具体是怎么思考的:

>>> 按照给定的格式回答以下问题,你可以使用下面这些工具:查询人物性别: 通过人名查找该人物的性别时用的工具,输入应该是人物的名字
根据性别推荐商品: 当知道了一个人性别后想进一步获得他可能感兴趣的商品时用的工具,输入应该是人物的性别回答时需要遵循以下用---括起来的格式:---
Question: 我需要回答的问题
Thought: 回答这个上述我需要做些什么
Action: ”查询人物性别, 根据性别推荐商品“ 中的其中一个工具名
Action Input: 选择工具所需要的输入
Observation: 选择工具返回的结果
...(这个思考/行动/行动输入/观察可以重复N次)
Thought: 我现在知道最终答案
Final Answer: 原始输入问题的最终答案
---现在开始回答,记得在给出最终答案前多按照指定格式进行一步一步的推理。Question: 我想送点礼物给张三LLM Output >>> Thought: 我需要知道张三的性别,才能更好地推荐礼物          # 模型的第一次输出
Action: 查询人物性别
Action Input: 张三现在开始回答,记得在给出最终答案前多按照指定格式进行一步一步的推理。Question: 我想送点礼物给张三LLM Output >>> Thought: 我需要知道张三的性别,才能更好地推荐礼物          # 模型的第一次输出
Action: 查询人物性别
Action Input: 张三

可以看到,模型进行了第一次思考,它认为解决这个问题首先需要 “确定人物性别”。

而模型之所以能够想到先 “确认性别”,其实是因为我们在 prompt 的最开始告诉了模型:

你可以使用下面这些工具:
查询人物性别: 通过人名查找该人物的性别时用的工具,输入应该是人物的名字
...

模型通过可用工具的描述来推测出自己当前应该怎么决策,所以文章前面也有提到:工具名+工具描述非常的重要!

现在,模型已经决定了要调用 find_gender 函数(Action),并且决定了函数的输入(Action Input)为「张三」,那么,LangChain 就会调用 find_gender(“张三”) 这个函数,得到结果为:男。

于是,我们的 prompt 模板就需要更新啦:

>>> 照给定的格式回答以下问题,你可以使用下面这些工具:查询人物性别: 通过人名查找该人物的性别时用的工具,输入应该是人物的名字
根据性别推荐商品: 当知道了一个人性别后想进一步获得他可能感兴趣的商品时用的工具,输入应该是人物的性别回答时需要遵循以下用---括起来的格式:---
Question: 我需要回答的问题
Thought: 回答这个上述我需要做些什么
Action: ”查询人物性别, 根据性别推荐商品“ 中的其中一个工具名
Action Input: 选择工具所需要的输入
Observation: 选择工具返回的结果
...(这个思考/行动/行动输入/观察可以重复N次)
Thought: 我现在知道最终答案
Final Answer: 原始输入问题的最终答案
---现在开始回答,记得在给出最终答案前多按照指定格式进行一步一步的推理。Question: 我想送点礼物给张三Thought: 我需要知道张三的性别,才能更好地推荐礼物       # 新添加的内容,这部分内容会随着思考不断增加
Action: 查询人物性别                               # 上一步使用的工具
Action Input: 张三                                # 上一步使用工具的输入
Observation: 男                                  # 上一步使用工具后得到的结果
Thought:

可以看到,在模板的最后添加了上一步模型思考的内容(Thought)、调用的工具(Action)、以及调用工具得到的结果(Observation)。

现在我们知道「性别」了,让模型接着往下思考吧:

>>> 照给定的格式回答以下问题,...
...
Thought: 我需要知道张三的性别,才能更好地推荐礼物       # 新添加的内容,这部分内容会随着思考不断增加
Action: 查询人物性别                               # 上一步使用的工具
Action Input: 张三                                # 上一步使用工具的输入
Observation: 男                                  # 上一步使用工具后得到的结果
Thought:LLM Output >>> 现在我知道了张三的性别,我可以根据性别推荐商品   # 接着上面的 prompt 做续写
Action: 根据性别推荐商品
Action Input: 男

模型现在决定调用 recommend_item() 函数,并且决定函数输入为「男」,调用函数 recommend_item(‘男’) 得到推荐结果:[‘Steam爆款’, ‘RTX-9090’, ‘iPhone 80’]

随后更新 prompt 模版,并喂给模型进行下一步决策:

>>> 按照给定的格式回答以下问题。你可以使用下面这些工具:
...
现在开始回答,记得在给出最终答案前多按照指定格式进行一步一步的推理。Question: 我想送点礼物给张三
Thought: 我需要知道张三的性别,才能更好地推荐礼物Action: 查询人物性别
Action Input: 张三
Observation: 男
Thought: 现在我知道了张三的性别,我可以根据性别推荐商品Action: 根据性别推荐商品
Action Input: 男
Observation: ['Steam爆款', 'RTX-9090', 'iPhone 80']
Thought: LLM Output >>> 现在我知道了可以推荐给张三的礼物,我可以给他送一个             # 模型根据已有的历史记录,得出了最终答案
Final Answer: 我可以给张三送一个Steam爆款、RTX-9090或者iPhone 80作为礼物。

现在已经得到足够多的信息,模型认为可以输出最终的答案了,因此输出「Final Answer:我可以送…」

而当我们解析到模型生成的内容中包含「Final Answer」关键字时,便可以让 Agent 停止思考并输出答案了。

最终的示例结果是这样:

User  >>> 我想送点礼物给张三
Model >>> 根据张三的性别和兴趣,我可以推荐Steam爆款、RTX-3090或iPhone 14作为礼物。
  1. 完整源码 示例的完整源码如下:
import os
import re
import json
from typing import List, Unionfrom langchain.agents import Tool, AgentExecutor, LLMSingleActionAgent, AgentOutputParser
from langchain.prompts import StringPromptTemplate
from langchain import OpenAI, SerpAPIWrapper, LLMChain
from langchain.schema import AgentAction, AgentFinishos.environ["OPENAI_API_KEY"] = "你的OpenAI key"def find_person(name: str):"""模拟本地数据库查询。Args:name (str): 人物名称,由LLM提取。Returns:_type_: _description_"""info = {'张三': '男','小红': '女'}return info.get(name, f'未找到{name}的性别信息,我应该直接返回 Observation: 未知')def recommend_item(gender: str):"""根据人物性别推荐不同的商品。Args:gender (str): 人物的性别,由 LLM 提取。Returns:_type_: _description_"""recommend = {'男': ['Steam爆款', 'RTX-9090', 'iPhone 80'],'女': ['夏季碎花裙', '轻盈帆布包', '琉璃唇釉'],'未知': ['AJ新品', '手冲咖啡']}return recommend.get(gender, f'未找到合适的推荐商品,我应该返回 Final Answer: 随便买些什么吧,只要消费就能快乐!')tools = [Tool(name = "查询人物性别",func=find_person,description="通过人名查找该人物的性别时用的工具,输入应该是人物的名字"),Tool(name = "根据性别推荐商品",func=recommend_item,description="当知道了一个人性别后想进一步获得他可能感兴趣的商品时用的工具,输入应该是人物的性别")
]template_zh = """按照给定的格式回答以下问题。你可以使用下面这些工具:{tools}回答时需要遵循以下用---括起来的格式:---
Question: 我需要回答的问题
Thought: 回答这个上述我需要做些什么
Action: ”{tool_names}“ 中的其中一个工具名
Action Input: 选择工具所需要的输入
Observation: 选择工具返回的结果
...(这个思考/行动/行动输入/观察可以重复N次)
Thought: 我现在知道最终答案
Final Answer: 原始输入问题的最终答案
---现在开始回答,记得在给出最终答案前多按照指定格式进行一步一步的推理。Question: {input}
{agent_scratchpad}
"""class CustomPromptTemplate(StringPromptTemplate):template: str           # 标准模板tools: List[Tool]       # 可使用工具集合def format(self, **kwargs) -> str:"""按照定义的 template,将需要的值都填写进去。Returns:str: 填充好后的 template。"""intermediate_steps = kwargs.pop("intermediate_steps")       # 取出中间步骤并进行执行thoughts = ""for action, observation in intermediate_steps:thoughts += action.logthoughts += f"\nObservation: {observation}\nThought: "kwargs["agent_scratchpad"] = thoughts                       # 记录下当前想法kwargs["tools"] = "\n".join([f"{tool.name}: {tool.description}" for tool in self.tools])    # 枚举所有可使用的工具名+工具描述kwargs["tool_names"] = ", ".join([tool.name for tool in self.tools])                        # 枚举所有的工具名称cur_prompt = self.template.format(**kwargs)print(cur_prompt)return cur_promptprompt = CustomPromptTemplate(template=template_zh,tools=tools,input_variables=["input", "intermediate_steps"]
)class CustomOutputParser(AgentOutputParser):def parse(self, llm_output: str) -> Union[AgentAction, AgentFinish]:"""解析 llm 的输出,根据输出文本找到需要执行的决策。Args:llm_output (str): _description_Raises:ValueError: _description_Returns:Union[AgentAction, AgentFinish]: _description_"""if "Final Answer:" in llm_output:       # 如果句子中包含 Final Answer 则代表已经完成return AgentFinish(return_values={"output": llm_output.split("Final Answer:")[-1].strip()},log=llm_output,)regex = r"Action\s*\d*\s*:(.*?)\nAction\s*\d*\s*Input\s*\d*\s*:[\s]*(.*)"   # 解析 action_input 和 actionmatch = re.search(regex, llm_output, re.DOTALL)if not match:raise ValueError(f"Could not parse LLM output: `{llm_output}`")action = match.group(1).strip()action_input = match.group(2)return AgentAction(tool=action, tool_input=action_input.strip(" ").strip('"'), log=llm_output)output_parser = CustomOutputParser()llm = OpenAI(temperature=0)
llm_chain = LLMChain(llm=llm, prompt=prompt
)tool_names = [tool.name for tool in tools]
agent = LLMSingleActionAgent(llm_chain=llm_chain, output_parser=output_parser,stop=["\nObservation:"], allowed_tools=tool_names
)agent_executor = AgentExecutor.from_agent_and_tools(agent=agent, tools=tools, verbose=True
)res = agent_executor.run("我想送点礼物给张三"
)
print(res)

总结

当然上面只是一个简单的用例,使用本地化定义的工具,大家可以尝试更多的工具。Tools的使用以及Agent应该是未来大模型应用的落地点,希望大家紧跟时代的齿轮。

如何学习AI大模型?

作为一名热心肠的互联网老兵,我决定把宝贵的AI知识分享给大家。 至于能学习到多少就看你的学习毅力和能力了 。我已将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。

这份完整版的大模型 AI 学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

一、全套AGI大模型学习路线

AI大模型时代的学习之旅:从基础到前沿,掌握人工智能的核心技能!

img

二、640套AI大模型报告合集

这套包含640份报告的合集,涵盖了AI大模型的理论研究、技术实现、行业应用等多个方面。无论您是科研人员、工程师,还是对AI大模型感兴趣的爱好者,这套报告合集都将为您提供宝贵的信息和启示。

img

三、AI大模型经典PDF籍

随着人工智能技术的飞速发展,AI大模型已经成为了当今科技领域的一大热点。这些大型预训练模型,如GPT-3、BERT、XLNet等,以其强大的语言理解和生成能力,正在改变我们对人工智能的认识。 那以下这些PDF籍就是非常不错的学习资源。

img

四、AI大模型商业化落地方案

img

作为普通人,入局大模型时代需要持续学习和实践,不断提高自己的技能和认知水平,同时也需要有责任感和伦理意识,为人工智能的健康发展贡献力量。

相关文章:

如何用 LangChain 实现一个Zero Shot智能决策器(附源码)

写在前面 最近一直在研究Agent和Tool的使用,今天给大家带来一篇何枝大佬(知乎何枝)的文章《如何用LangChain实现一个Zero Shot智能决策器》,并附上源码。 知乎:https://zhuanlan.zhihu.com/p/627333499LangChain是当…...

读完这本书,我终于搞懂了Transformer、BERT和GPT!【附PDF】

前言 《Transformer、BERT和GPT: 包括ChatGPT和提示工程》 是一本深入浅出地介绍自然语言处理领域前沿技术的专著,全书一共379页PDF,是截止到目前比较系统介绍NLP和GPT融合领域的书籍。 全书共十章,内容丰富,结构清晰&#xff0c…...

仿RabbitMq简易消息队列基础篇(Muduo库的使用)

TOC Muduo库简介 Muduo由陈硕⼤佬开发,是⼀个基于⾮阻塞IO和事件驱动的C⾼并发TCP⽹络编程库。他是一款基于主从Reactor模型的网络库,其使用的线程模型是one loop per thread, 所谓 one loop per thread 指的是: 一个线程只能有一个事件循…...

.net SqlSugarHelper

NuGet安装: SqlSugarCore using SqlSugar; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;namespace Namespace {public class SqlSugarHelper{public string _connectionString Custom…...

“AI能不能代替某某职业”,到底谁在破防?

前几天,公司在午间分享时谈到一个有趣的辩题:“AI能不能代替产品经理”,不仅双方辩手打了个你来我往,就连下面的吃瓜群众也进入红温状态。 “AI能不能代替xx”已经成为一个普遍的话题,在某乎上随手一刷就是不同的职业…...

智慧图书馆:构建高效视频智能管理方案,提升图书馆个性化服务

一、背景分析 随着信息技术的飞速发展,智慧图书馆作为现代公共文化服务的重要载体,正逐步从传统的纸质阅读空间向数字化、智能化方向转型。其中,视频智能管理方案作为智慧图书馆安全管理体系的重要组成部分,不仅能够有效提升图书…...

React快速开发框架

本框架主要用于快速搭建项目 使用的基本库:webpackreactreact-routertypescript ps:有不足之处请多多包涵,提出意见或者建议 目的: 前端开发大多数时间是基于市面上比较流行的成品框架开始进行开发,途中遇到的问题大…...

【前端】记录各种控制台警告/bug

一、Element Plus 1、控制台警告:“Runtime directive used on component with non-element root node. The directives will not function as intended.” 错误原因:在 Vue 组件上使用了运行时指令(指那些在运行时动态绑定到 DOM 元素上的指…...

猫咪掉毛严重怎么办?铲屎官家庭必备清理工具——宠物空气净化器

“毛,毛,毛,还是毛!”铲屎官们每天都离不开和猫毛斗智斗勇,家里的每个角落都成了“战场”,掉毛的严重程度超乎想象。有时也在后悔当初怎么不养只无毛猫,而是把毛孩子接了回来,世上没…...

顺序表的实现——数据结构

线性表 文章目录 线性表线性表的定义和基本操作线性表的定义线性表的基本操作 线性表的顺序表示顺序表的定义顺序表的实现——静态分配顺序表的实现——动态分配顺序表的特点 线性表的定义和基本操作 线性表的定义 线性表(Linear List)的定义 ​ 线性…...

【模块化】CommonJS,AMD规范,CMD规范,ES6模块化

1. CommonJS Node.js基于CommonJS规范应运而生 1.1 commonjs规范语法导出模块 module.exports { a, b }1.2 commonjs规范语法引入模块 const mod require(./导出模块name)2. AMD 规范 RequireJS 是AMD规范的实现。是js文件和模块的加载器。 在没有单页应用(angu…...

3.js - 顶点着色器、片元着色器的联系

1、定义与功能 顶点着色器 顶点着色器,是图形渲染管线中的第一个可编程阶段,它的主要任务是,处理从CPU发送到GPU的顶点数据,包括:1、顶点位置的变换(如:模型空间 -> 世界空间 -> 视图控件…...

kotlin简介

Kotlin 是一种在 Java 虚拟机上运行的静态类型编程语言,被称之为 Android 世界的Swift,由 JetBrains 设计开发并开源。 Kotlin 可以编译成Java字节码,也可以编译成 JavaScript,方便在没有 JVM 的设备上运行。 在Google I/O 2017…...

Mintegral出海系列:解锁全球应用商店新增长路径

在全球化竞争的浪潮中,面对打法各异的应用和游戏品类,以及全球数百个环境不同的国家和地区,开发者们正面临着前所未有的挑战。Mintegral「出海ing」系列专题内容,助力出海开发者选准赛道探索新的增长路径。 据近期数据显示&#x…...

Qt 哈希加密之 QCryptographicHash

【写在前面】 QCryptographicHash 是 Qt 框架中提供的一个类,它用于实现加密散列函数,也就是我们常说的哈希函数。哈希函数能够将任意长度的数据转换为固定长度的哈希值,这个哈希值通常用于数据的完整性校验、密码存储等场景。 什么是哈希函数…...

渗透第二次作业

目录 简述rce漏洞 可能产生rce漏洞的函数 RCE代码执行漏洞示例 贷齐乐系统多处SQL注入漏洞 ​编辑 爆出库名 爆出表名 爆出表下的列名 查flag数据 简述rce漏洞 ​ rce漏洞,即远程代码执行和远程命令执行漏洞。这种漏洞允许攻击者在后台服务器上远程注入操作…...

42.【C语言】冒泡排序

目录: 冒泡排序 *核心思想 *分析 *代码 *优化 15.冒泡排序(bubble sort) *核心思想:两两相邻的元素进行比较,满足条件则两者交换 *分析 现要求升序排序 输入: 9 8 7 6 5 4 3 2 1 0 输出:0 1 2 3 4 5 6 7 8 9 下面展示一趟冒泡排…...

Linux安全与高级应用(七)深入Linux Shell脚本编程:循环与分支结构的高级应用

文章目录 深入Linux Shell脚本编程:循环与分支结构的高级应用一、循环结构详解1. for循环1.1 应用示例:检查主机状态 2. while循环2.1 应用示例:猜价格游戏 二、分支结构详解1. if语句1.1 单分支结构1.2 双分支结构1.3 多分支结构 2. case语句…...

python爬虫滑块验证及各种加密函数(基于ddddocr进行的一层封装)

git链接: https://github.com/JOUUUSKA/spider_toolsbox 这里写目录标题 一.识别验证码1、识别英文+数字验证码2、识别滑块验证码3、识别点选验证码 一.识别验证码 git链接: https://github.com/JOUUUSKA/spider_toolsbox 创作不易记得stars 1、识别英文&#xf…...

pytorch学习一(扩展篇):miniconda下载、安装、配置环境变量。miniconda创建多版本python环境。整理常用命令(亲测ok)

文章目录 前言一、miniconda和anaconda的关系1、Anaconda2、Miniconda3、总结 二、下载miniconda(清华镜像链接)三、安装miniconda1、安装2、或许要手动加载 ~/.bashrc 四、配置 命令1、查看anaconda安装博文2、取消默认进入conda(base&#…...

CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型

CVPR 2025 | MIMO:支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题:MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者:Yanyuan Chen, Dexuan Xu, Yu Hu…...

椭圆曲线密码学(ECC)

一、ECC算法概述 椭圆曲线密码学(Elliptic Curve Cryptography)是基于椭圆曲线数学理论的公钥密码系统,由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA,ECC在相同安全强度下密钥更短(256位ECC ≈ 3072位RSA…...

ssc377d修改flash分区大小

1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...

Go 语言接口详解

Go 语言接口详解 核心概念 接口定义 在 Go 语言中,接口是一种抽象类型,它定义了一组方法的集合: // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的: // 矩形结构体…...

基于Uniapp开发HarmonyOS 5.0旅游应用技术实践

一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架,支持"一次开发,多端部署",可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务,为旅游应用带来&#xf…...

Keil 中设置 STM32 Flash 和 RAM 地址详解

文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...

[10-3]软件I2C读写MPU6050 江协科技学习笔记(16个知识点)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16...

视频字幕质量评估的大规模细粒度基准

大家读完觉得有帮助记得关注和点赞!!! 摘要 视频字幕在文本到视频生成任务中起着至关重要的作用,因为它们的质量直接影响所生成视频的语义连贯性和视觉保真度。尽管大型视觉-语言模型(VLMs)在字幕生成方面…...

ArcGIS Pro制作水平横向图例+多级标注

今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作:ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等(ArcGIS出图图例8大技巧),那这次我们看看ArcGIS Pro如何更加快捷的操作。…...

Python ROS2【机器人中间件框架】 简介

销量过万TEEIS德国护膝夏天用薄款 优惠券冠生园 百花蜂蜜428g 挤压瓶纯蜂蜜巨奇严选 鞋子除臭剂360ml 多芬身体磨砂膏280g健70%-75%酒精消毒棉片湿巾1418cm 80片/袋3袋大包清洁食品用消毒 优惠券AIMORNY52朵红玫瑰永生香皂花同城配送非鲜花七夕情人节生日礼物送女友 热卖妙洁棉…...