LangChain:模型 I/O 封装使用解析和感触

目录

模型 API:LLM vs. ChatModel

OpenAI 模型封装

多轮对话 Session 封装

换个国产模型

模型的输入与输出

Prompt 模板封装

PromptTemplate

ChatPromptTemplate

MessagesPlaceholder

从文件加载 Prompt 模板

TXT模板

Yaml模板

Json模板

输出封装 OutputParser

​编辑Pydantic (JSON) Parser

Auto-Fixing Parser

总结

关键点提取

使用感触


        本文将继续延续Langchain专栏文章,本文将讲解Langchain的模型 I/O 封装。Langchain将不同的模型,统一封装成一个接口,方便更换模型而不用重构代码。

        对Langchain能做什么暂时还不了解的话可以移步先看这篇文章

直通车:LangChain:大模型框架的深度解析与应用探索-CSDN博客

模型 API:LLM vs. ChatModel

pip install --upgrade langchain # 安装最新版本
pip install --upgrade langchain-openai # v0.1.0新增的底包

OpenAI 模型封装

        最基本的调度封装

from langchain_openai import ChatOpenAI

llm = ChatOpenAI(model="gpt-3.5-turbo")  # 默认是gpt-3.5-turbo
response = llm.invoke("你是谁")
print(response.content)

多轮对话 Session 封装

# 加载 .env 到环境变量
from dotenv import load_dotenv, find_dotenv
_ = load_dotenv(find_dotenv())

from langchain_openai import ChatOpenAI

llm = ChatOpenAI()  # 默认是gpt-3.5-turbo

from langchain.schema import (
    AIMessage, #等价于OpenAI接口中的assistant role
    HumanMessage, #等价于OpenAI接口中的user role
    SystemMessage #等价于OpenAI接口中的system role
)
messages = [
    SystemMessage(content="从现在开始你叫AI助手-小京。"),
    HumanMessage(content="我是CSDN的一名博主,我叫Muller"),
    AIMessage(content="欢迎!"),
    HumanMessage(content="我是谁")
]
response = llm.invoke(messages)
print(response.content)

通过模型封装,实现不同模型的统一接口调用

        SystemMessage 描述你的大模型角色、功能、作用等等;

        HumanMessage 用户输入的内容 

        AIMessage 大模型回答

        通过这个Message数组就能表示一个摘要,原生的Openai通过一个json数组,每一轮都一个任务一个content来去表示一个对话上下文,那么在langchain的框架下,可以通过它定义的结构来去表示一个对话。然后呢,我们还是把这个对话通过invoke接口来传给大模型,就实现了这一种多轮对话的交互。

        和Openai一样,对话历史还是需要我们自行进行管理的 ,具体langchain这个框架下需要如何管理对话历史后面再详细讲解。也就是说它不会自动帮我们填充里面的信息,例如你不附上content,它返回的实际上就是一个ai message ,如果你要维护这一个上下文的话,那你就需要将这个ai message填到数组里去发起下轮,就是这么一个逻辑。

换个国产模型

pip install qianfan
# 加载 .env 到环境变量
from dotenv import load_dotenv, find_dotenv
_ = load_dotenv(find_dotenv())

# 其它模型分装在 langchain_community 底包中
from langchain_community.chat_models import QianfanChatEndpoint
from langchain.schema import HumanMessage
import os
qianfan = QianfanChatEndpoint(
    qianfan_ak=os.getenv('ERNIE_CLIENT_ID'),
    qianfan_sk=os.getenv('ERNIE_CLIENT_SECRET')
)

messages = [
    HumanMessage(content="你是谁")
]

response = qianfan.invoke(messages)
print(response.content)

        通过这么一个简单的例子就能体会到模型的封装的一个好处就是不同的模型我都用统一的接口去调用,如果都是openai我就不用管你是3.5还是4,我都统一用这个接口,甚至我换一个模型,还是这样一个结构去调用,我接口是不用变的。

模型的输入与输出

Prompt 模板封装

PromptTemplate

        对一段文字生成了一个提示词模板。提供了一个函数将字符串转成一个模板。

from langchain.prompts import PromptTemplate
print("====模板====")
template = PromptTemplate.from_template("帮我解释一下这个成语:{idiom}")
print(template)
print("====提示词====")
print(template.format(idiom='繁花似锦'))

         模板包含两个元素,一个是模板内容,另一个是模板内代填的变量给提取出来。

====模板====
input_variables=['idiom'] template='帮我解释一下这个成语:{idiom}'
====提示词====
#帮我解释一下这个成语:繁花似锦

ChatPromptTemplate

        提供了把一个多轮对话上下文整个变成一个多轮模板的形式,用模板表示的对话上下文。

# 加载 .env 到环境变量
from dotenv import load_dotenv, find_dotenv
_ = load_dotenv(find_dotenv())

from langchain.prompts import ChatPromptTemplate
from langchain.prompts.chat import SystemMessagePromptTemplate, HumanMessagePromptTemplate
from langchain_openai.chat_models import ChatOpenAI

# 定义聊天提示词
template = ChatPromptTemplate.from_messages(
    [
        SystemMessagePromptTemplate.from_template("你是一名{subject}老师,你的名字叫{name}"),
        HumanMessagePromptTemplate.from_template("{query}"),
    ]
)

llm = ChatOpenAI()
# 生成大模型输入
prompt = template.format_messages(
        subject="语文",
        name="muller",
        query="告诉我你是谁,然后帮我解释一下这个成语:繁花似锦"
    )

response = llm.invoke(prompt)
print(response.content)

#你好,我是一名语文老师,名叫Muller。

#繁花似锦是一个形容词成语,用来形容景色美丽、繁华盛开的样子。其中,“繁花”指的是许多花朵,而“似#锦”则表示美丽多彩、如锦绣般的样子。
#这个成语常用来形容春天或夏天花朵盛开的景象,也可以用来形容其他美丽的景色或事物。它表达了繁花##绚烂的美丽,给人以愉悦和喜悦的感觉。

MessagesPlaceholder

        通过MessagesPlaceholder把多轮对话整个变成模板,它的作用就是解决逐轮对话写入麻烦的问题,例如上述代码,需要不断在from_messages填充多个元素表示多轮对话,当历史对话发生变化需重新填充,因为对话历史本身就是一个Message List,那么就可以直接把message List填写到对话的中间,如下列代码MessagesPlaceholder(variable_name="历史对话") 留了一个多轮的占位符  ,给该占位符取了一个名字为:“历史对话”。

# 加载 .env 到环境变量
from dotenv import load_dotenv, find_dotenv
_ = load_dotenv(find_dotenv())

from langchain.prompts import (
    ChatPromptTemplate,
    MessagesPlaceholder,
)
from langchain.prompts.chat import  HumanMessagePromptTemplate
from langchain_openai.chat_models import ChatOpenAI
llm = ChatOpenAI()

# 定义一个用户对话模板
human_message_template = HumanMessagePromptTemplate.from_template("帮我解释一下这个成语: {idiom}.")

# 定义当前聊天提示词,传参 历史聊天记录和用户对话模板
chat_prompt = ChatPromptTemplate.from_messages(
    # variable_name 是 message placeholder 在模板中的变量名
    # 用于在赋值时使用
    [MessagesPlaceholder(variable_name="历史对话"), human_message_template]
)

#定义大模型角色说明,AI、Human、System
from langchain_core.messages import AIMessage, HumanMessage,SystemMessage

#大模型角色说明
system_message = SystemMessage(content="你是一名语文老师,你的名字叫muller")
#用户对话1
human_message = HumanMessage(content="告诉我你是谁?")
#大模型回答1
ai_message = AIMessage(content="我是一名语文老师,名叫Muller")

# 生成大模型输入
messages = chat_prompt.format_prompt(
    # 对 "conversation" 和 "language" 赋值
    历史对话=[system_message,human_message, ai_message], idiom="繁花似锦"
)

print(messages.to_messages())


result = llm.invoke(messages)
print(result.content)

# 繁花似锦是一个形容词成语,用来形容景色美丽、繁华盛开的样子。其中,“繁花”指的是许多花朵,而# “似锦”则表示美丽多彩、如锦绣般的样子。

# 这个成语常用来形容春天或夏天花朵盛开的景象,也可以用来形容其他美丽的景色或事物。它表达了繁花# 绚烂的美丽,给人以愉悦和喜悦的感觉。

从文件加载 Prompt 模板

        我们在开发模式可以通过在代码中通过字符串定义模板,但实际生产中则需要将代码和prompt进行分离,这样便于整个项目的管理。Langchain也提供了像SK一样的能力,可以支持加载一个文件为Prompt模板,例如Txt加载方式是将字符串放到了txt文件中。 

TXT模板

帮我解释一下这个成语:{idiom}
from langchain.prompts import PromptTemplate

template = PromptTemplate.from_file("example_prompt_template.txt")
print("===Template===")
print(template)
print("===Prompt===")
print(template.format(topic='繁花似锦'))

# ===Template===
# input_variables=['idiom'] template='帮我解释一下这个成语:{idiom}'
#===Prompt===
# 帮我解释一下这个成语:繁花似锦

Yaml模板

    _type: prompt
    input_variables:
        ["subject", "idiom"]
    template: 
        你是一名{subject}老师,帮我解释一下这个成语:{idiom}
from langchain.prompts import load_prompt
prompt = load_prompt("simple_prompt.yaml")
print(prompt.format(subject="语文", idiom="繁花似锦"))

Json模板

{
    "_type": "prompt",
    "input_variables": ["idiom"],
    "template": "帮我解释一下这个成语:{idiom}"
}
from langchain.prompts import load_prompt
prompt = load_prompt("simple_prompt.json")
print(prompt.format(subject="语文", idiom="繁花似锦"))

输出封装 OutputParser

        自动把 LLM 输出的字符串按指定格式加载,如果通过规定格式输出,对程序解析有好处。

        LangChain 内置的 OutputParser 包括但不仅限于:

  • ListParser
  • DatetimeParser
  • EnumParser
  • JsonOutputParser
  • PydanticParser
  • XMLParser

详细用例直通车:Output Parsers | 🦜️🔗 LangChain

Pydantic (JSON) Parser

        我们可以使用python的Pydantic类,去定义一个特定的结构,且这个结构是带含义描述的结构体,然后这个结构体我们可以从JSON结构中转换成它,也可以将它转换成JSON格式。而Langchain就是提供了解析Pydantic结构对象的能力。

        打个比方有个日期类,日期有“年”、“月”、“日” 和 “公元前/公元后” 这四个字段组成。假设我们需要一个这个类的对象,那么我们就可以通过依据Pydantic类格式将它描述出来,然后用Langchain提供的Pydantic解析器让大模型按这个格式输出结果,然后用Parser从大模型的结果里去解析出这个对象来,后面就可以让依据程序逻辑使用这个结构化的结果了。

        具体例子如下:一般描述类属性对象已具备基本能力,但如果你需要校验对象值的合法性,就需要用到Pydantic的能力,即@validator和@staticmethod的注解内容。 

# 定义Pydantic结构
from langchain_core.pydantic_v1 import BaseModel, Field, validator
from typing import List, Dict

# 定义你的输出对象

class Date(BaseModel):
    year: int = Field(description="Year")
    month: int = Field(description="Month")
    day: int = Field(description="Day")
    era: str = Field(description="BC or AD")

    # ----- 可选机制 --------
    # 你可以添加自定义的校验机制
    @validator('month')
    def valid_month(cls, field):
        if field <= 0 or field > 12:
            raise ValueError("月份必须在1-12之间")
        return field

    @validator('day')
    def valid_day(cls, field):
        if field <= 0 or field > 31:
            raise ValueError("日期必须在1-31日之间")
        return field

    @validator('day', pre=True, always=True)
    def valid_date(cls, day, values):
        year = values.get('year')
        month = values.get('month')

        # 确保年份和月份都已经提供
        if year is None or month is None:
            return day  # 无法验证日期,因为没有年份和月份

        # 检查日期是否有效
        if month == 2:
            if cls.is_leap_year(year) and day > 29:
                raise ValueError("闰年2月最多有29天")
            elif not cls.is_leap_year(year) and day > 28:
                raise ValueError("非闰年2月最多有28天")
        elif month in [4, 6, 9, 11] and day > 30:
            raise ValueError(f"{month}月最多有30天")

        return day

    @staticmethod
    def is_leap_year(year):
        if year % 400 == 0 or (year % 4 == 0 and year % 100 != 0):
            return True
        return False
#使用Pydantic
from langchain.prompts import PromptTemplate
from langchain_openai import ChatOpenAI

from langchain.output_parsers import PydanticOutputParser

model_name = 'gpt-3.5-turbo'
temperature = 0
model = ChatOpenAI(model_name=model_name, temperature=temperature)

# 根据Pydantic对象的定义,构造一个OutputParser
parser = PydanticOutputParser(pydantic_object=Date)

template = """提取用户输入中的日期。
{format_instructions}
用户输入:
{query}"""

prompt = PromptTemplate(
    template=template,
    input_variables=["query"],
    # 直接从OutputParser中获取输出描述,并对模板的变量预先赋值
    partial_variables={"format_instructions": parser.get_format_instructions()}
)

print("====Format Instruction=====")
print(parser.get_format_instructions())


query = "2024年五月1日即将实施的《非银行支付机构监督管理条例》,将非银行支付机构及其业务活动进一步纳入法治化轨道进行监管。"
model_input = prompt.format_prompt(query=query)

print("====Prompt=====")
print(model_input.to_string())

output = model(model_input.to_messages())
print("====模型原始输出=====")
print(output)
print("====Parse后的输出=====")
date = parser.parse(output.content)
print(date)
====Format Instruction=====
The output should be formatted as a JSON instance that conforms to the JSON schema below.

As an example, for the schema {"properties": {"foo": {"title": "Foo", "description": "a list of strings", "type": "array", "items": {"type": "string"}}}, "required": ["foo"]}
the object {"foo": ["bar", "baz"]} is a well-formatted instance of the schema. The object {"properties": {"foo": ["bar", "baz"]}} is not well-formatted.

Here is the output schema:
```
{"properties": {"year": {"title": "Year", "description": "Year", "type": "integer"}, "month": {"title": "Month", "description": "Month", "type": "integer"}, "day": {"title": "Day", "description": "Day", "type": "integer"}, "era": {"title": "Era", "description": "BC or AD", "type": "string"}}, "required": ["year", "month", "day", "era"]}
```
====Prompt=====
提取用户输入中的日期。
The output should be formatted as a JSON instance that conforms to the JSON schema below.

As an example, for the schema {"properties": {"foo": {"title": "Foo", "description": "a list of strings", "type": "array", "items": {"type": "string"}}}, "required": ["foo"]}
the object {"foo": ["bar", "baz"]} is a well-formatted instance of the schema. The object {"properties": {"foo": ["bar", "baz"]}} is not well-formatted.

Here is the output schema:
```
{"properties": {"year": {"title": "Year", "description": "Year", "type": "integer"}, "month": {"title": "Month", "description": "Month", "type": "integer"}, "day": {"title": "Day", "description": "Day", "type": "integer"}, "era": {"title": "Era", "description": "BC or AD", "type": "string"}}, "required": ["year", "month", "day", "era"]}
```
用户输入:
2024年五月1日即将实施的《非银行支付机构监督管理条例》,将非银行支付机构及其业务活动进一步纳入法治化轨道进行监管。

====模型原始输出=====
content='{"year": 2024, "month": 5, "day": 1, "era": "AD"}'
====Parse后的输出=====
year=2024 month=5 day=1 era='AD'

Auto-Fixing Parser

        Openai不一定保证百分之百每一次结果输出的格式你要的能一模一样,例如返回的内容都是中文或json格式错误等问题,所以大模型输出的结果本身存在一定的不确定性,那就导致如果格式错了,那么OutputParser解析会失败,为了失败了能够再次尝试去自动修复这个格式上的错误,重新解析,Langchain还提供了Auto-Fixing Paser。

        核心它完成了大模型输出的结果是错的,导致解析失败时,它会尝试修改格式再做一次自动的解析。定义这块功能需要将原始的Parser给它,同时还需要给它大模型对象。

# 加载 .env 到环境变量
from dotenv import load_dotenv, find_dotenv
_ = load_dotenv(find_dotenv())

from langchain_core.pydantic_v1 import BaseModel, Field, validator

# 定义你的输出对象
class Date(BaseModel):
    year: int = Field(description="Year")
    month: int = Field(description="Month")
    day: int = Field(description="Day")
    era: str = Field(description="BC or AD")

    # ----- 可选机制 --------
    # 你可以添加自定义的校验机制
    @validator('month')
    def valid_month(cls, field):
        if field <= 0 or field > 12:
            raise ValueError("月份必须在1-12之间")
        return field

    @validator('day')
    def valid_day(cls, field):
        if field <= 0 or field > 31:
            raise ValueError("日期必须在1-31日之间")
        return field

    @validator('day', pre=True, always=True)
    def valid_date(cls, day, values):
        year = values.get('year')
        month = values.get('month')

        # 确保年份和月份都已经提供
        if year is None or month is None:
            return day  # 无法验证日期,因为没有年份和月份

        # 检查日期是否有效
        if month == 2:
            if cls.is_leap_year(year) and day > 29:
                raise ValueError("闰年2月最多有29天")
            elif not cls.is_leap_year(year) and day > 28:
                raise ValueError("非闰年2月最多有28天")
        elif month in [4, 6, 9, 11] and day > 30:
            raise ValueError(f"{month}月最多有30天")

        return day

    @staticmethod
    def is_leap_year(year):
        if year % 400 == 0 or (year % 4 == 0 and year % 100 != 0):
            return True
        return False

from langchain.prompts import PromptTemplate
from langchain_openai import ChatOpenAI

from langchain.output_parsers import PydanticOutputParser

model_name = 'gpt-3.5-turbo'
temperature = 0
model = ChatOpenAI(model_name=model_name, temperature=temperature)

# 根据Pydantic对象的定义,构造一个OutputParser
parser = PydanticOutputParser(pydantic_object=Date)

template = """提取用户输入中的日期。
{format_instructions}
用户输入:
{query}"""

prompt = PromptTemplate(
    template=template,
    input_variables=["query"],
    # 直接从OutputParser中获取输出描述,并对模板的变量预先赋值
    partial_variables={"format_instructions": parser.get_format_instructions()}
)


query = "2024年五月1日即将实施的《非银行支付机构监督管理条例》,将非银行支付机构及其业务活动进一步纳入法治化轨道进行监管。"
model_input = prompt.format_prompt(query=query)


output = model(model_input.to_messages())

# 解决output输出尽量可控
from langchain.output_parsers import OutputFixingParser

new_parser = OutputFixingParser.from_llm(parser=parser, llm=ChatOpenAI(model="gpt-3.5-turbo"))

# 因为这个例子比较简单,大模型比较难出错,这里手动替换成错误值
output = output.content.replace("5", "五月")
print("===格式错误的Output===")
print(output)
try:
    date = parser.parse(output)
except Exception as e:
    print("===出现异常===")
    print(e)

# 用OutputFixingParser自动修复并解析
date = new_parser.parse(output)
print("===重新解析结果===")
print(date)
===格式错误的Output===
{"year": 2024, "month": 五月, "day": 1, "era": "AD"}
===出现异常===
Failed to parse Date from completion {"year": 2024, "month": 五月, "day": 1, "era": "AD"}. Got: Expecting value: line 1 column 25 (char 24)
===重新解析结果===
year=2024 month=5 day=1 era='AD'

总结

关键点提取

本文关键内容提取:

        1、LangChain 统一封装了各种模型的调用接口,包括补全型和对话型两种;
        2、LangChain 提供了 PromptTemplate 类,可以自定义带变量的模板;
        3、LangChain 提供了一些列输出解析器,用于将大模型的输出解析成结构化对象;额外带有自动修复功能;
        4、模型属于 LangChain 中较为优秀的部分;美中不足的是 OutputParser 自身的 Prompt 维护在代码中,耦合度较高。

使用感触

从这段时间接触Langchain,从使用角度上感触如下:

  • Langchain对大模型的封装是可用的。对此结论的评价标准是假设即使不用Langchian的情况下,自己去设计一套应用,同样对大模型调用接口上也进行一个类似抽象,自己是否能保证从chatgpt模型切到claude模型后不会造成代码大规模的调整,在这个尝试上我发现是Langchain可行的,并且所调整的代码极少。
  • Langchain对于PromptTemplate的封装在早期的确实很粗糙,但现在的版本基本达到可用状态。不难看出从字符串加载、从文件加载,甚至嵌套方式加载目前都已具备了,所以PromptTemplate这个功能从个人而言并没有发现特别大的弊端导致不推荐的情况,因此可以认为它也是一个可用的模块,而且即使你不用Langchain来管理,你也可以来参考它这种模式,就是将Prompt和代码分开来管理,以完成填槽的逻辑。
  • OutputParser情况却没有很理想,首先它是基本可用的,例如JsonParser这些基础解析是可用的,但Auto-Fixing Parser则需要注意的就是它自己内部是有Prompt模板的。它的Prompt模板写的如何,在你的这个业务中是否通用?是否未来对所有的模型都兼容?这些是需要酌情考虑使用的。在使用这些非代码的功能,即不确定的功能的时候,需要注意的是不能因为模型变化了结果却不是最优解的情况,例如当初是基于gpt4编写生产好用,而更换到gpt5了它的这个模板就不是最优解了,或导致该功能就失效了。这里我更推荐的一个做法就是使用这些内置Prompt模板功能或不确定的代码时候,强烈推荐能够单独将这部分Prompt抽出来管理,就是把Prompt抽出来去维护,哪怕真的要用它写的功能也要拷贝出来单独维护,这样的好处在于未来你的模型换了,出现非最优解时,你能知道改哪里,好导致你不用梳理整个逻辑改整块代码。

        

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

使用模拟SPI接口驱动串行接口的LCD( STM32F4)

目录 概述 1. 硬件介绍 1.1 ST7796-LCD 1.2 MCU IO与LCD PIN对应关系 2 代码实现 2.1 STM32CubeMX 6.11生成工程 2.2 IO模拟SPI接口 2.3 实现LCD的驱动 3 测试 测试代码下载地址&#xff1a; stm32-f407-lcd-ft6336-proj资源-CSDN文库 gitee下载地址&#xff1a; h…

48. 旋转图像/240. 搜索二维矩阵 II

48. 旋转图像 给定一个 n n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。 你必须在 原地 旋转图像&#xff0c;这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。 示例 &#xff1a; 输入&#xff1a;matrix [[5,1,9,11],[2,4,…

NodeMCU ESP8266 获取I2C从机地址

文章目录 前言关于地址位读写位程序总结前言 I2C总线上可以挂载很多的从设备,每个设备都会有一个自己唯一的一个地址; 关于地址位 通常地址位占7位数据,主设备如果需要向从机发送/接收数据,首先要发送对应从机的地址,然后会匹配总线上挂载的从机的地址; 读写位 该位…

81.网络游戏逆向分析与漏洞攻防-移动系统分析-飞天遁地的实现与面向计算

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 如果看不懂、不知道现在做的什么&#xff0c;那就跟着做完看效果&#xff0c;代码看不懂是正常的&#xff0c;只要会抄就行&#xff0c;抄着抄着就能懂了 内容…

服装定制|基于SSM+vue的服装定制系统的设计与实现(源码+数据库+文档)

服装定制系统 目录 基于SSM&#xff0b;vue的服装定制系统的设计与实现 一、前言 二、系统设计 三、系统功能设计 1系统功能模块 2管理员功能模块 3用户后台管理模块 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&#xf…

【CTF Web】QSNCTF 文章管理系统 Writeup(SQL注入+Linux命令+RCE)

文章管理系统 题目描述 这是我们的文章管理系统&#xff0c;快来看看有什么漏洞可以拿到FLAG吧&#xff1f;注意&#xff1a;可能有个假FLAG哦 解法 SQL 注入。 ?id1 or 11 --取得假 flag。 爆库名。 ?id1 union select 1,group_concat(schema_name) from information_sch…

【机器学习】集成学习在信用评分领域实例

集成学习在信用评分领域的应用与实践 一、引言二、集成学习的概念与原理三、集成学习在信用评分中的应用实例四、总结与展望 一、引言 在当今金融数字化快速发展的时代&#xff0c;信用评分成为银行、金融机构等评估个人或企业信用风险的重要工具。然而&#xff0c;单一的信用评…

飞天使-k8s知识点31-rancher的正确打开方式

文章目录 安装之前优化一下内核参数以及系统内核版本 rancher安装主要是使用以下命令nginx的配置为解决办法 安装之前优化一下内核参数以及系统内核版本 内核版本 4.17 cat > /etc/modules-load.d/iptables.conf <<EOF ip_tables iptable_filter EOF 然后重启服务器…

STM32快速入门(定时器之输出PWM波形)

STM32快速入门&#xff08;定时器之输出PWM波形&#xff09; 前言 本节主要讲解STM32利用通用定时器&#xff0c;利用CCR和CNT寄存器&#xff0c;输出指定占空比和频率的PWM波形。其功能的应用有&#xff1a;实现LED呼吸灯的效果、控制步进电机、控制直流电机转速等。 导航 …

基于FPGA的NC图像质量评估verilog实现,包含testbench和MATLAB辅助验证程序

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 vivado2019.2和matlab2022a测试&#xff0c;结果如下&#xff1a; 2.算法运行软件版本 vivado2019.2 matlab2022a 3.部分核心程序 timescale …

解决vue3项目打包后部署后某些静态资源图片不加载问题

目录 问题 原因 解决方案 问题 开发完项目打包并部署 然后访问时发现导航栏背景图片没加载 打开浏览器控制台发现这张图片报错404 原因 可能是因为在部署后的服务器环境中对中文文件名的支持不完善。服务器在解析 URL 时可能无法正确识别或编码中文字符&#xff0c;导致无…

高精度原理介绍及代码实现

目录 高精度 引入 使用场景 实现原理 高精度加法 数据存储 加法实现 总代码 高精度减法 与加法的不同点&#xff1a; 总代码 高精度乘法 总代码 高精度除法 总结 总注意点 减法注意点 高精度 引入 所谓高精度并不是很高级难懂的东西&#xff0c;只是对传统的…

Kubernetes 核心概念

kubernetes的对象 Kubernetes 包含多种类型的资源对象&#xff1a;Pod、Label、Service、Replication Controller 等。 所有的资源对象都可以通过 Kubernetes 提供的 kubectl 工具进行增、删、改、查等操作&#xff0c;并将其保存在 etcd 中持久化存储。 Kubernets其实是一个…

【JAVA进阶篇教学】第十三篇:Java中volatile关键字讲解

博主打算从0-1讲解下java进阶篇教学&#xff0c;今天教学第十三篇&#xff1a;volatile关键字讲解。 在 Java 中&#xff0c;volatile关键字是一种轻量级的同步机制&#xff0c;用于确保变量的可见性和禁止指令重排序。本文将详细解释volatile关键字的工作原理、可见性保证以及…

对称加密介绍

一、什么是对称加密 对称密钥算法(Symmetric-key algorithm)&#xff0c;又称为对称加密、私钥加密、共享密钥加密&#xff0c;是密码学中的一类加密算法。 对称加密的特点是&#xff0c;在加密和解密时使用相同的密钥&#xff0c;或是使用两个可以简单地相互推算的密钥。 这…

Zynq开发-使用PYNQ快速入门摄像头MIPI驱动(OV5640)-overlay设计

目录 1. 简介 2. Overlay 设计 2.1 总体设计 2.2 MIPI 子系统 2.3 去马赛克 2.4 AXI_IIC 3. 注意事项 4. 总结 1. 简介 本文是关于《Zynq开发-使用PYNQ快速入门摄像头MIPI驱动(OV5640)-CSDN博客》的博客文章&#xff0c;涉及了overlay设计的Vivado工程细节。在使用PYN…

iZotope RX 11 for Mac 激活版:让您的音频焕发生机!

在追求音频完美的道路上&#xff0c;iZotope RX 11 for Mac是您的得力助手。它凭借先进的音频修复技术和丰富的音频增强工具&#xff0c;让您的音频作品焕发出前所未有的生机与活力。无论您是专业的音频工程师&#xff0c;还是业余的音乐爱好者&#xff0c;都能在这款工具中找到…

【Spring】验证 @ServerEndpoint 的类成员变量线程安全

文章目录 前言猜想来源验证方法Controller 的情况ServerEndpoint 的情况 后记 前言 最近有 websocket 的需求。探索 ServerEndpoint 的类成员变量特点。 这里类比 Controller 讨论 ServerEndpoint 类成员变量是否线程安全。 猜想来源 网上的教程大多数都这么展示程序&#…

OBS插件--音频采集

音频采集 音频采集是一款 源 插件,类似于OBS的win-capture/game-capture&#xff0c;允许从特定应用程序捕获音频&#xff0c;而不是捕获整个系统的音频。避免了因为特定音频的采集而需要引入第三方软件&#xff0c;而且时延也非常低。 下面截图演示下操作步骤&#xff1a; 首…

HCIP-Datacom-ARST自选题库_06_排障【28道题】

一、单选题 1.如果面对复杂的网络故障&#xff0c;并经过评估认为短时间内无法完成排障&#xff0c;而此时用户又急需恢复网络的可用性&#xff0c;那么正确的做法是? 告诉用户这是不可能实现的 不通知客户的情况下&#xff0c;直接搭建替代的网络环境 始终尝试排除故障&a…