Rasa学习笔记
一、CALM
三个关键要素:
- 业务逻辑:Flow,描述了AI助手可以处理的业务流程
- 对话理解:旨在解释最终用户与助手沟通的内容。此过程涉及生成反映用户意图的命令,与业务逻辑和正在进行的对话的上下文保持一致。
- 自动对话修复:修复处理会话“脱离脚本”的所有方式
CALM使用一种称为对话理解(DU)的新方法,将用户所说的内容转化为对业务逻辑的意义,关键点:
- DU输出一系列命令,表示用户希望如何推进对话,而不是像NLU系统那样产生意图和实体
- NLU系统被限制在一个固定的意图列表中,而DU是生成性的,根据内部语法产生一系列命令。这为我们提供了一种更丰富的语言来表达用户的需求。
- 使用CALM比构建基于NLU的助手要快得多。CALM不依赖于意图,使用一个名为Flows的原语来定义对话逻辑
CALM使用LLM来确定用户希望如何推进对话。它不使用LLM来猜测完成该过程的正确步骤集。相比于LLM Agent,CALM可以确保业务逻辑被明确地遵循
二、工作流
在CALM中,AI助手的业务逻辑被实现为一组流。每个流程都描述了您的AI助手完成任务所使用的逻辑步骤。它描述了用户需要的信息、需要从API或数据库检索的数据,以及基于收集的信息的分支逻辑。
1. 流的定义
flows:a_flow: # required idname: "A flow" # optional namedescription: "required description of what the flow does"always_include_in_prompt: false # optional boolean, defaults to falseif: "condition" # optional flow guardnlu_trigger: # optional list of intents that can start a flow- intent: "starting_flow_intent"persisted_slots: [] # optional list of slots that should be persisted at the conversation level after the flow endssteps: [] # required list of steps
- description:必填,描述流程为用户做了什么。编写清晰的描述很重要,因为对话理解组件使用它来决定何时开始此流程
- always_include_in_prompt:如果always_include_in_prompt字段设置为true,并且If字段中定义的流保护计算结果为true,则该流将始终包含在提示中
- nlu_trigger:可以启动该流的意图。
- persisted_slots:默认情况下,当流程结束时,在collect和set_slot步骤中设置的插槽将被重置。要更改此行为,可以将这些插槽添加到persisted_slots字段中,其值应在流结束后持久化。且这些slot必须在collect 或 set_slots步骤中被填充
- steps:列出了流程步骤,有以下几种类型
- action step: 由流运行的自定义动作或话语动作
- collect step:向用户提出一个问题以填充一个插槽
- call step:调用另一个流的步骤
- link step:在该流完成后链接另一个流的步骤
- set slots step:设置插槽的步骤
- noop步骤:创建条件的步骤
step有id和next两个属性,用来标识当前步骤和下一个步骤,如果不标识next,则使用列表中的下一步
- collect: namenext: the_next_step
- id: the_next_stepcollect: age
匿名next
- collect: namenext:- collect: age- collect: agenext:- if: slots.age < 18then:- action: utter_not_old_enoughnext: END- if: slots.age >= 18 and slots.age < 65then: 18_to_65_step- else: over_65_step
2. Step
- action:action_do_something执行命令,不需要等用户输入
- action: action_check_sufficient_funds
- collect:用户需要输入的slot,可以添加描述字段以指导语言模型提取槽值
- collect: account_typedescription: "Account type is one of checking, savings, money market, or IRA."ask_before_filling:truereset_after_flow_ends:falseutter: utter_ask_secondary_account_type- collect: agerejections:- if: slots.age < 1utter: utter_invalid_age- if: slots.age < 18utter: utter_age_at_least_18next: ask_email
默认情况下,如果slot已被提取则跳过收集步骤,ask_before_filling设置为true则依旧需要询问。可以设置为false,在域文件中添加默认值
slots:dress_type:type: categoricalvalues:- "shirt"- "pants"- "jacket"mappings:- type: customdress_size:type: categoricalvalues:- "small"- "medium"- "large"mappings:- type: custom
默认情况下,当流程完成时,通过收集步骤填充的所有插槽都会重置。一旦流结束,插槽的值要么重置为null,要么重置为插槽的初始值。如果要在流完成后保留插槽的值,将reset_after_flow_ends属性设置为false。该设置和persisted_slots字段冲突
utter_ask_{slot_name}可以为收集的slot定义不同的key
actions:- action_ask_{slot_name}
使用action_ask_{slot_name}可以自定义收集步骤,如想将从数据库中获取的插槽的可用值显示为按钮
rejections属性用于slot的验证,如果if条件为True,则返回utter定义的内容。如果没有通过验证,助手会自动尝试再次收集信息,直到值没有被拒绝,并默认返回Sorry,可以通过utter_internal_error_rasa修改
对于更复杂的验证逻辑,您还可以在自定义操作中定义插槽验证。请注意,此自定义操作必须遵循以下命名约定:validate_{slot_name}。
- link:
链接只能用作流程的最后一步。当达到链接步骤时,当前流结束,目标流开始。
- link: "id_of_another_flow"
- call:可以在流(父流)中使用调用步骤来嵌入另一个流(子流)。当执行到达调用步骤时,CALM会启动子流。子流完成后,执行将继续父流。
flows:parent_flow:steps:- call: child_flowchild_flow:if: Falsesteps:- action: utter_child_flow
子流遇到next:END,则控件将传递回父流
激活子流时,父流的插槽不会重置。子流可以访问和修改父流的插槽。当控件返回到父流时,子流的插槽将不会重置。
如果在子流中触发CancelFlow()命令,父流也将被取消。
为了防止子流直接被用户消息触发,您可以在子流中添加流保护if: False,该流只有在父流调用它时才会触发。
另外,子流不能使用link
如果用例要求启动一个流作为另一个流的后续,那么link更适合完成两个流之间的连接。但是,如果一个流需要表现得像是另一个更大流的一部分,并且在子流完成后需要在更大流内执行更多步骤,那么应该使用call。
- set_slots:设置slot的值,主要用于取消设置插槽值。例如,如果用户要求转账的金额超过了他们账户中的可用金额,您可能需要通知他们。只需重置金额槽,而不是结束流程。
flows:transfer_money:description: This flow lets users send money to friends and family.steps:- collect: recipient- id: ask_amountcollect: amountdescription: the number of US dollars to send- action: action_check_sufficient_fundsnext:- if: not has_sufficient_fundsthen:- action: utter_insufficient_funds- set_slots:- amount: nullnext: ask_amount- else: final_confirmation
- noop:不需要actions、collect就能创建分支条件
flows:change_address:description: Allow a user to change their address.steps:- noop: truenext:- if: not slots.authenticatedthen:- call: authenticate_usernext: ask_new_address- else: ask_new_address- id: ask_new_addresscollect: address
3. 条件表达式
支持 not、and、or、is、is not 、contains、matches等
命名空间:
- slots:用于访问插槽值
- context:用于访问当前对话帧属性
pattern_completed:description: a flow has been completed and there is nothing else to be donesteps:- noop: truenext:- if: context.previous_flow_name != "greeting"then:- action: utter_what_can_help_withnext: END- else: stop- id: stopaction: action_stop
对话管理器在对话框架堆栈中组织流(用户定义和内置)的推进。对话帧堆栈表示LIFO(后进先出)对话帧堆栈。不同类型的对话框架被映射到内置的对话模式,以实现对话修复。
每个对话帧都有一个flow_id和step_id属性。flow_id是当前流的id,step_id是流中当前步骤的id。
4. 流的启动
nlu_trigger:包含一个可以启动流的意图列表,可以通过confidence_threshold添加置信区间阈值
flows:my_flow:description: "A flow triggered with <intent-name>"nlu_trigger:- intent:name: <intent-name>confidence_threshold: 0 # threshold value, optionalsteps:- action: my_action
在流定义中添加额外的if字段来指定流保护,但是如果是通过link,call,intent触发的则可以绕过限制
flows:show_latest_bill:description: A flow with a flow guard.if: slots.authenticated AND slots.email_verifiedsteps:- action: my_action
三、对话理解
CALM的对话理解模块将带有对话上下文的最新用户消息转换为一组命令,助手使用这些命令来执行定义的业务逻辑。它是在命令生成器的帮助下完成的
目前支持以下几种命令生成器:
- SingleStepLLMCommandGenerator
- MultiStepLLMCommandGenerator
- NLUCommandAdapter
如果想同时利用LLM和经典的NLU管道来预测命令,那么可以通过在基于LLM的命令生成器之前添加NLUCommandAdapter来实现
一般来说,如果第一个命令生成器预测了一个命令,则管道中接下来的所有其他命令生成器都会被跳过。
config.yml
pipeline:
# - ...- name: NLUCommandAdapter- name: SingleStepLLMCommandGenerator
# - ...
生成的命令包含以下:
- Start Flow、Cancel Flow、Skip Question、Set Slot、Correct Slots、Clarify、Chit-Chat Answer、Knowledge Answer、Human Handoff、Error、Cannot Handle、Change Flow
四、域
域定义了助手的活动空间,包括:
- Responses:发送给用户的响应模板
- Actions:操作
- Slots:对话的记忆
- Session配置,如超时时间
1. Slots
插槽在域的插槽部分中定义,包含其名称、类型和默认值。存在不同的插槽类型来限制插槽可以取的可能值。
插槽类型:text、bool、categorical、float、any、list
slots:risk_level:type: categoricalvalues:- low- medium- high
- Slot Mappings
NLUCommandAdapter将NLU管道的输出(意图和实体)与域文件中定义的槽映射进行匹配。如果满足插槽映射,NLUCommandAdapter将发出设置插槽命令来填充插槽。
- from _ lm
可以使用from_llm槽映射类型用基于llm的命令生成器生成的值填充槽。如果域文件中没有明确定义映射,则这是默认的插槽映射类型。
slots:user_name:type: textmappings:- type: from_llm
在这个例子中,user_name插槽将填充基于LLM的命令生成器生成的值。允许基于LLM的命令生成器在会话流中的任何点填充此槽,而不仅仅是在该槽的相应收集步骤。NLUCommandAdapter将跳过任何具有from_llm映射的插槽,并且不会发出set插槽命令来填充这些插槽。
- Mapping Conditions:可以定义在填充插槽之前满足插槽映射的条件。如果定义了映射到同一实体的多个插槽,但不希望在提取实体时填充所有插槽,则这特别有用
entities:
- personslots:first_name:type: textmappings:- type: from_entityentity: personconditions:- active_flow: greet_userlast_name:type: textmappings:- type: from_entityentity: personconditions:- active_flow: issue_invoiceinitial_value: "xx"shared_for_coexistence: True
- 自定义Slot Mappings
actions:
- action_fill_user_nameslots:user_name:type: textmappings:- type: customaction: action_fill_user_name
- 基于LLM的生成器在对话的任何时候都无法用基于NLU的预定义映射填充插槽。
- 在插槽名称的collect步骤中,基于LLM的生成器将不会处于活动状态。如果您希望用户话语包含离题或其他意图,而不仅仅是设置插槽的信息,那么您应该使用NLU触发器来处理流中的这些特定意图。
- 基于LLM的生成器可以在不收集插槽名称且具有from_LLM映射类型的步骤中填充其他插槽。
initial_value可以指定插槽的默认值
shared_for_coexistence属性指定共享一些CALM和基于NLU的系统都应该能够使用的插槽,如基于NLU的系统和CALM都应该能够知道用户是否登录。如果选项shared_for_coexistence未设置为true,则流定义中的reset_after_flow_ends:False属性将无效
2. Session配置
- session_expiration_time:定义了新会话开始后的不活动时间(分钟)。
- carry_over_slots_to_new_session:决定是否应将现有的插槽转移到新会话
默认配置:
session_config:session_expiration_time: 60 # value in minutes, 0 means infinitely longcarry_over_slots_to_new_session: true # set to false to forget slots between sessions
这意味着,如果用户在60分钟不活动后发送了第一条消息,则会触发一个新的对话会话,并且任何现有的插槽都会被转移到新会话中。
五、事件
Rasa Pro中的每个对话都代表一系列事件。事件用于跟踪用户消息和机器人响应,以及Rasa Pro在对话中采取的行动,如推进流程或设置插槽。Rasa Pro在对话的不同阶段发出事件,可以通过查询Rasa Pro分析数据管道或运行端到端测试来分析和改进您的助手
事件存储在Rasa Pro tracker store中,可以通过Rasa Pro HTTP API进行额外访问。
六、Responses
响应是助手发送给用户的消息。响应通常只是文本,但也可以包括图像和按钮等内容。
响应位于域文件中的Responses键下或单独的“Responses.yml”文件中。每个响应名称都应该以utter_开头。
responses:utter_greet:- text: "Hi there!"utter_bye:- text: "See you!"
可以使用变量将信息插入到响应中。如下Rasa会自动用名为name的插槽中的值填充变量。如果这样的槽不存在或为空,则变量将填充None。
可以设置多个响应内容,会随机返回其中一个
channel属性会根据用户连接到的通道指定不同的响应变化
responses:utter_greet:- text: "Hey, {name}. How are you?"channel: "slack"- text: "Hey, {name}. How is your day going?"
根据条件决定返回值
slots:logged_in:type: boolinfluence_conversation: Falsemappings:- type: customname:type: textinfluence_conversation: Falsemappings:- type: customresponses:utter_greet:- condition:- type: slotname: logged_invalue: truetext: "Hey, {name}. Nice to see you again! How are you?"- text: "Welcome. How is your day going?"
Rephraser
通过使用LLM来改写静态响应模板,机器人生成的响应听起来会更自然、更具对话性,从而增强用户交互。
通过配置 rephrase: True 来开启重写。也可以开启全局重写。rephrase_prompt用来添加提示词
responses:utter_greet:- text: "Hey! How can I help you?"metadata:rephrase: Truerephrase_prompt: |The following is a conversation withan AI assistant. The assistant is helpful, creative, clever, and very friendly.Rephrase the suggested AI response staying close to the original message and retainingits meaning. Use simple english.Context / previous conversation with the user:{{history}}{{current_input}}Suggested AI Response: {{suggested_response}}Rephrased AI Response:
历史对话配置
nlg:- type: rephrasesummarize_history: False // 摘要模式max_historical_turns: 5 // 转录模式,保留最后n次对话的直接转录。
此外,可以配置使用的大模型、温度等参数
七、组件
1. 配置文件
通过配置文件config.yml定义需要的组件和策略
recipe: default.v1
language: en
assistant_id: 20230405-114328-tranquil-mustardpipeline:- name: SingleStepLLMCommandGeneratorpolicies:- name: rasa.core.policies.flow_policy.FlowPolicy
- pipeline:用于处理和理解最终用户发送助手的消息的组件
pipeline:- name: SingleStepLLMCommandGeneratorllm:model_group: openai_llmflow_retrieval:embeddings:model_group: text_embedding_modeluser_input:max_characters: 420
- policies:助手将用于推进对话的对话策略
2. 模型组配置
LLM通常被部署在一个或多个组中,模型组允许在一个ID下定义多个模型,任何组件都可以使用该ID
模型组在endpoints.yml文件的model_groups键下定义
model_groups:- id: openai_llmmodels:- provider: openaimodel: gpt-4-0613api_key: ${MY_OPENAI_API_KEY}- id: openai-gpt-35-turbomodels:- provider: openaimodel: gpt-3.5-turbotimeout: 7
需要使用环境变量使用${}
embedding模型也在model下配置
model_groups:- id: text_embedding_modelmodels:- provider: openaimodel: text-embedding-ada-002
3. 路由组件
根据路由组件决定将消息路由到NLU系统还是CALM系统,有两个路由组件可供选择:
- IntentBasedRouter:NLU管道预测意图用于决定消息应该去哪里
- LLMBasedRouter:此组件利用LLM来决定消息是应该路由到基于NLU的系统还是CALM
在config.yml中配置即可
- name: IntentBasedRouternlu_entry:sticky:- transfer_money- check_balance- search_transactionsnon_sticky:- chitchatcalm_entry:sticky:- book_hotel- cancel_hotel- list_hotel_bookings
- nlu_entry:
- sticky:应该以sticky方式路由到基于NLU的系统的意图列表。
- non_stricky:应以非粘性方式路由到基于NLU的系统的意图列表。
- calm_entry:
- sticky:应该以粘性方式路由到CALM的意图列表。
4. LLM 命令生成器
LLM 命令生成器利用上下文学习来输出一系列命令,这些命令表示用户希望如何推进对话
当前支持两种LLM 命令生成器:
- SingleStepLLMCommandGenerator
- MultiStepLLMCommandGenerator
生成器使用的默认prompt模板由静态部分和动态部分组成。动态部分由当前的上下文内容渲染得到。也可以自定义模板,自定义模板可以使用{}来获取流信息插槽信息
pipeline:- name: SingleStepLLMCommandGeneratorprompt_template: prompts/command-generator.jinja2
{% for flow in available_flows %}
{{ flow.name }}: {{ flow.description }}{% for slot in flow.slots -%}slot: {{ slot.name }}{% if slot.description %} ({{ slot.description }}){% endif %}{% if slot.allowed_values %}, allowed values: {{ slot.allowed_values }}{% endif %}{% endfor %}
{%- endfor %}
MultiStepLLMCommandGenerator使用上下文学习在上下文中解释用户的消息,将任务分解为几个步骤,使LLM的工作更容易,步骤包括:
- 处理流程(开始、结束等)
- 填充插槽
因此也包含两套prompt:handle_flows和 fill_slots

- 如果当前没有活动的流,则使用handle_flows提示符来启动或澄清流。
- 如果启动了一个流,接下来将执行fill_slots提示符来填充新启动的流的任何槽。
- 如果流当前处于活动状态,则调用fill_slots提示符来填充当前活动流的任何新插槽。如果用户消息(也)指示,例如,应启动新流或取消活动流,则会触发ChangeFlow命令。这导致调用handle_flows提示符来启动、取消或澄清流。如果该提示导致启动流,则再次执行fill_slots提示以填充该新流的任何槽。
同样的,MultiStepLLMCommandGenerator的prompt模板也可以自定义
pipeline:- name: MultiStepLLMCommandGeneratorprompt_templates:handle_flows:file_path: prompts/handle_flows_template.jinja2fill_slots:file_path: prompts/fill_slots_template.jinja2
5. 相关流召回
随着助理技能的发展,功能流程的数量可能会扩展到数百个。然而,由于LLM上下文窗口的限制,将所有这些流同时呈现给LLM是不切实际的。为了确保效率,只考虑与给定对话相关的流的子集。我们实现了一个流检索机制,以识别和过滤命令生成器最相关的流。这种有针对性的选择有助于在LLM的上下文窗口范围内制定有效的提示。
在训练过程中,所有定义的流,都会被转换为包含流描述、插槽描述的文档。然后使用嵌入模型将这些文档转换为向量,并存储在向量存储中。当与助手交谈时,即在推理过程中,当前对话上下文被转换为向量,并与向量存储中的流进行比较。此比较确定了与当前对话上下文最相似的流,并将其包含在SingleStepLLMCommandGenerator和MultiStepLLMComandGenerator的提示中
always_include_in_prompt设置为true,则该流总会被包含在prompt内
相关流召回功能默认是开启的,流召回的表现取决于流描述的质量
自定义prompt,提升准确率的技巧:
- 提供详细的信息描述:确保流程描述准确且信息丰富,直接概述流程的目的和范围。力求简洁和信息密度之间的平衡,使用命令式语言,避免不必要的单词,以防止歧义。目标是尽可能清楚地传达基本信息。
- 使用清晰标准的语言:避免不寻常的措辞或措辞。坚持使用清晰、普遍理解的语言
- 明确定义上下文:明确定义流上下文,以提高模型的情境感知能力
- 澄清隐性知识:澄清描述中的任何专业知识
- 添加用户输入示例
pipeline:- name: SingleStepLLMCommandGenerator...flow_retrieval:embeddings:model_group: openai_text_embeddingturns_to_embed: 1should_embed_slots: truenum_flows: 20
- embeddings:模型选择,默认使用text-embedding-ada-002
- turns_to_embed:要转换为向量的对话次数。将该值设置为1意味着只使用最新的对话回合
- should_embed_slots:是否在训练期间将槽描述与流描述一起嵌入
- num_flows:从向量存储中检索的最大流数
6. 多模型路由器
model_groups:- id: azure_llm_deploymentsmodels:- provider: azuredeployment: gpt-4-instance-franceapi_base: https://azure-deployment-france/api_version: "2024-02-15-preview"api_key: ${MY_AZURE_API_KEY_FRANCE}- provider: azuredeployment: gpt-4-instance-canadaapi_base: https://azure-deployment-canada/api_version: "2024-02-15-preview"api_key: ${MY_AZURE_API_KEY_CANADA}router:routing_strategy: simple-shuffle
在endpoints.yml中配置router实现多个模型的负载均衡。建议模型组配置中的模型部署使用相同的底层模型
可选的路由策略:
- simple-shuffle:基于RPM(每分钟请求数)或权重进行分配
- least-busy:把请求分发到正在进行的请求数量最少的模型
- latency-based-routing:将请求分发到响应时间最短的模型
需要配置Redis的策略:
- cost-based-routing:以最低成本将请求分发到部署。
- usage-based-routing:向TPM(每分钟令牌数)使用率最低的部署分发请求
7. Policy
policies:- name: FlowPolicy- name: EnterpriseSearchPolicy
可以配置多个策略,在每一个转折点,配置中定义的每个策略都有机会以一定的置信度预测下一个操作。策略也可以决定不预测任何行动。最高置信度的策略决定了助理的下一步行动。
- FlowPolicy
流策略是一个状态机,它确定性地执行流中定义的业务逻辑。流策略监督助手的状态,处理状态转换,并在会话修复需要时启动新流。
FlowPolicy采用对话堆栈结构(后进先出)和内部插槽来管理对话的状态。
- Intentless Policy
无意图策略用于发送在域中定义的Response,但这些Response不是任何流的一部分。这有助于有效地处理闲聊、上下文问题和高风险话题
policies:- name: IntentlessPolicyprompt: prompts/intentless-policy-template.jinja2
可以通过在config.yml中设置prompt属性来更改用于生成Response的prompt
无意图策略通常可以以零样本方式选择正确的响应。可以通过添加示例对话来提高策略的性能,将端到端的故事添加到data/e2e_stories.yml到您的训练数据中。这些对话将被用作示例,以帮助学习无障碍政策。可以定义您的助手可以发送的经过审查的、人工撰写的回复
- story: currenciessteps:- user: How many different currencies can I hold money in?- action: utter_faq_4- story: automatic transfers travelsteps:- user: Can I add money automatically to my account while traveling?- action: utter_faq_5- story: user gives a reason why they can't visit the branchsteps:- user: I'd like to add my wife to my credit card- action: utter_faq_10- user: I've got a broken leg- action: utter_faq_11
此外,对于高风险的话题,最安全的方法是发送一个自包含的、经过审查的答案,而不是依赖于生成模型。无障碍政策在CALM助理中提供了这种能力。
相关文章:
Rasa学习笔记
一、CALM 三个关键要素: 业务逻辑:Flow,描述了AI助手可以处理的业务流程对话理解:旨在解释最终用户与助手沟通的内容。此过程涉及生成反映用户意图的命令,与业务逻辑和正在进行的对话的上下文保持一致。自动对话修复…...
list_for_each_entry_safe 简介
list_for_each_entry_safe 是 Linux 内核中用于遍历链表的一个宏,特别适用于在遍历过程中可能需要删除链表节点的场景。它的设计保证了在删除当前节点时,不会影响后续节点的访问,从而实现安全的遍历。 定义 #define list_for_each_entry_sa…...
Android 系统面试问题
一.android gki和非gki的区别 Android GKI(Generic Kernel Image)和非GKI内核的主要区别在于内核设计和模块化程度,具体如下: 1. 内核设计 GKI:采用通用内核设计,与设备硬件分离,核心功能统一…...
【面试集锦】如何设计SSO方案?和OAuth有什么区别?
如何设计SSO方案?和OAuth有什么区别?--楼兰 带你聊最纯粹的Java 如果面试问你,你会做一个权限系统吗?那你肯定会说做过。不就是各种登录、验证吗。我做的第一个CRUD应用就是注册、登录。简单!但是,如果问你在工作中真的做过权限系统吗?其实很多人都只能默默摇摇头。因…...
二十六、使用docsify搭建文档管理平台
特性 无需构建,写完文档直接发布容易使用并且轻量 (~19kB gzipped)智能的全文搜索提供多套主题丰富的 API...
bitcoinjs学习1—P2PKH
1. 概述 在本学习笔记中,我们将深入探讨如何使用 bitcoinjs-lib 库构建和签名一个 P2PKH(Pay-to-PubKey-Hash) 比特币交易。P2PKH 是比特币网络中最常见和最基本的交易类型之一,理解其工作原理是掌握比特币交易构建的关键。 想要详…...
如何在 Java 应用中实现数据库的主从复制(读写分离)?请简要描述架构和关键代码实现?
在Java应用中实现数据库主从复制(读写分离) 一、架构描述 (一)整体架构 主库(Master) 负责处理所有的写操作(INSERT、UPDATE、DELETE等)。它是数据的源头,所有的数据变…...
【pytest】获取所有用例名称并存于数据库
数据库操作包,引用前面创建的py文件,【sqlite】python操作sqlite3(含测试) #!/usr/bin/env python # -*- coding: utf-8 -*- # Time : 2025-02-11 8:45 # Author : duxiaowei # File : get_filename.py # Software: 这个文…...
【论文笔记】Are Self-Attentions Effective for Time Series Forecasting? (NeurIPS 2024)
官方代码https://github.com/dongbeank/CATS Abstract 时间序列预测在多领域极为关键,Transformer 虽推进了该领域发展,但有效性尚存争议,有研究表明简单线性模型有时表现更优。本文聚焦于自注意力机制在时间序列预测中的作用,提…...
maven导入spring框架
在eclipse导入maven项目, 在pom.xml文件中加入以下内容 junit junit 3.8.1 test org.springframework spring-core ${org.springframework.version} org.springframework spring-beans ${org.springframework.version} org.springframework spring-context ${org.s…...
AUTOGPT:基于GPT模型开发的实验性开源应用程序; 目标设定与分解 ;;自主思考与决策 ;;信息交互与执行
目录 AUTOGPT是一款基于GPT模型开发的实验性开源应用程序目标设定与分解自主思考与决策信息交互与执行AUTOGPT是一款基于GPT模型开发的实验性开源应用程序 目标设定与分解 自主思考与决策 信息交互与执行 AUTOGPT是一款基于GPT模型开发的实验性开源应用程序,它能让大语言模…...
瑞芯微开发板/主板Android调试串口配置为普通串口方法 深圳触觉智能科技分享
本文介绍瑞芯微开发板/主板Android调试串口配置为普通串口方法,不同板型找到对应文件修改,修改的方法相通。触觉智能RK3562开发板演示,搭载4核A53处理器,主频高达2.0GHz;内置独立1Tops算力NPU,可应用于物联…...
Redis 数据类型 Hash 哈希
在 Redis 中,哈希类型是指值本⾝⼜是⼀个键值对结构,形如 key "key",value { { field1, value1 }, ..., {fieldN, valueN } },Redis String 和 Hash 类型⼆者的关系可以⽤下图来表⽰。 Hash 数据类型的特点 键值对集合…...
IntelliJ IDEA 2024.1.4版无Tomcat配置
IntelliJ IDEA 2024.1.4 (Ultimate Edition) 安装完成后,调试项目发现找不到Tomcat服务: 按照常规操作添加,发现服务插件中没有Tomcat。。。 解决方法 1、找到IDE设置窗口 2、点击Plugins按钮,进入插件窗口,搜索T…...
连锁收银系统的核心架构与技术选型
在连锁门店的日常运营里,连锁收银系统扮演着极为重要的角色,它不仅承担着交易结算的基础任务,还关联着库存管理、会员服务、数据分析等多个关键环节。一套设计精良的核心架构与合理的技术选型,是保障收银系统高效、稳定运行的基础…...
CSS 小技巧 —— CSS 实现 Tooltip 功能-鼠标 hover 之后出现弹层
CSS 小技巧 —— CSS 实现 Tooltip 功能-鼠标 hover 之后出现弹层 1. 两个元素实现 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><title>纯 CSS 实现 Tooltip 功能-鼠标 hover 之后出现弹层</titl…...
19.4.2 -19.4.4 新增、修改、删除数据
版权声明:本文为博主原创文章,转载请在显著位置标明本文出处以及作者网名,未经作者允许不得用于商业目的。 需要北风数据库的请留言自己的信箱。 19.4.2 新增数据 数据库数据的新增、修改和删除不同于查询,查询需要返回一个DbD…...
【PL/SQL】常用操作复习20250212
目录标题 1.基本语法结构二级目录三级目录 1.基本语法结构2。变量声明和使用3. SELECT 查询4.插入 insert5.更新UPDATE6.删除(DELETE) 7游标 cursor例子1:基本游标使用例子2:使用FOR循环的简化写法实际应用例子:给高工资员工增加奖金 8 IF 条…...
C++自研游戏引擎-碰撞检测组件-八叉树AABB检测算法实现
八叉树碰撞检测是一种在三维空间中高效处理物体碰撞检测的算法,其原理可以类比为一个管理三维空间物体的智能系统。这个示例包含两个部分:八叉树部分用于宏观检测,AABB用于微观检测。AABB可以更换为均值或节点检测来提高检测精度。 八叉树的…...
haproxy详解笔记
一、概述 HAProxy(High Availability Proxy)是一款开源的高性能 TCP/HTTP 负载均衡器和代理服务器,用于将大量并发连接分发到多个服务器上,从而提高系统的可用性和负载能力。它支持多种负载均衡算法,能够根据服务器的…...
windows 通过docker 安装mysql
参考:Docker安装并使用Mysql(可用详细)_docker 安装mysql-CSDN博客 1. 拉取镜像:docker pull mysql:5.7 2. 查看镜像:docker image 3. 创建mysql 容器实例,并将data 目录挂载到本地d盘上 docker run --n…...
【STM32】通过L496的HAL库Flash建立FatFS文件系统(CubeMX自动配置R0.12C版本)
【STM32】通过L496的HAL库Flash建立FatFS文件系统(CubeMX自动配置R0.12C版本) 文章目录 FlashFlash地址写Flash地址读 FatFS文件系统配置FatFS移植驱动函数时间戳函数 文件操作函数工作区缓存文件挂载和格式化测试文件读写测试其他文件操作函数 测试附录…...
QTreeView笔记
1.定义TreeModel类 我们需要继承自QAbstractItemModel,让我们来看看它有哪些接口。 QAbstractItemModel类中定义如下: Q_INVOKABLE virtual QModelIndex index(int row, int column, const QModelIndex &parent QModelIndex()) const 0;Q_INVOK…...
传感器篇(一)——深度相机
目录 一 概要 二 原理 三 对比 四 产品 五 结论 一 概要 深度相机是一种能够获取物体深度信息的设备,相较于普通相机只能记录物体的二维图像信息,深度相机可以感知物体与相机之间的距离,从而提供三维空间信息。在你正在阅读的报告中提到…...
Qt 控件整理 —— 按钮类
一、PushButton 1. 介绍 在Qt中最常见的就是按钮,它的继承关系如下: 2. 常用属性 3. 例子 我们之前写过一个例子,根据上下左右的按钮去操控一个按钮,当时只是做了一些比较粗糙的去演示信号和槽是这么连接的,这次我们…...
校园网绕过认证上网很简单
校园网绕过认证就是不用通过校园WiFi的WEB页面登录,这个WEB登录页面就是认证页面. 所谓绕过认证,就是不通过校园WiFi WEB登录页面直接上网,校园WiFi没有密码,直接就能连接上,我们连上这个WiFi的时候,它会给…...
蓝桥杯篇---温度传感器 DS18B20
文章目录 前言DS18B201. DS18B20 引脚说明2. 单总线通信协议3. DS18B20 操作流程初始化写操作读操作 4. 示例代码5. 代码说明6. 注意事项总结 前言 以上就是今天要讲的内容,本文简单介绍了IAP15F2K61S2中温度传感器模块DS18B20的使用。 DS18B20 DS18B20 是一款数字…...
WPS或word接入智能AI
DeepSeek接入WPS 配置WPS (1)下载 OfficeAl助手插件: 插件下载地址:https://www.office-ai.cn/。 安装插件后,打开WPS,菜单栏会新增"OfficeAl助手”选项卡。 如果没有出现, 左上找到文件菜单 -> 选项 ,在…...
vue3:template中v-for循环遍历这个centrerTopdata,我希望自循环前面三个就可以了怎么写?
问: template中v-for循环遍历这个centrerTopdata,我希望自循环前面三个就可以了怎么写? 回答: 问: <div v-for"(item, index) in centrerTopdata.slice(0, 3)" :key"index"> div cl…...
Java练习(20)
ps:练习来自力扣 给你一个 非空 整数数组 nums ,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。 你必须设计并实现线性时间复杂度的算法来解决此问题,且该算法只使用常量额外空间。 class Solution {pu…...
