【吴恩达deeplearning.ai】基于LangChain开发大语言应用模型(上)

news2024/11/14 10:52:42

以下内容均整理来自deeplearning.ai的同名课程

Location 课程访问地址

DLAI - Learning Platform Beta (deeplearning.ai)

一、什么是LangChain

1、LangChain介绍

LangChain是一个框架,用于开发由大语言模型驱动的应用程序。开发者相信,最强大的、差异化的应用不仅会调用语言模型,而且还会具备以下原则:
数据感知:将语言模型与其他数据源连接起来。
代理性:允许语言模型与环境互动

LangChain支持python和javascript两种语言。专注于组合和模块化。
官方文档:https://python.langchain.com/en/latest/
中文文档:https://www.langchain.com.cn/

2、LangChain的模块化能力

包括大量的整合对话模型、聊天模型;提示词模板,输出分析器,示例选择器。

支持检索和调用其他数据源,包括不限于文本、数组,支持多个数据检索工具。

支持搭建对话链模板,按输入信息,自动生成标准化加工后的输出结果。

可调用多个预设或者自定义的算法和小工具。

二、模型、提示词和输出解析器Models, Prompts and Output Parsers

1、Prompt template提示词模板

通常来说,我们通过以下方式调用gpt

def get_completion(prompt, model="gpt-3.5-turbo"):
    messages = [{"role": "user", "content": prompt}]
    response = openai.ChatCompletion.create(
        model=model,
        messages=messages,
        temperature=0, 
    )
    return response.choices[0].message["content"]
# 创建一个调用函数

prompt = f"""Translate the text \
that is delimited by triple backticks 
into a style that is {style}.
text: ```{customer_email}```
"""
# 编写提示语

response = get_completion(prompt)
#调用生成结果

现在看下langchain怎么基于模型进行调用

from langchain.chat_models import ChatOpenAI
chat = ChatOpenAI(temperature=0.0)
# 加载langchain对话模型,并设置对话随机性为0

template_string = """Translate the text \
that is delimited by triple backticks \
into a style that is {style}. \
text: ```{text}```
"""
# 设计模板信息

from langchain.prompts import ChatPromptTemplate
prompt_template = ChatPromptTemplate.from_template(template_string)
# 加载提示语模板,载入模板信息

customer_style = """American English \
in a calm and respectful tone
"""
customer_email = """
Arrr, I be fuming that me blender lid \
flew off and splattered me kitchen walls \
with smoothie! And to make matters worse, \
the warranty don't cover the cost of \
cleaning up me kitchen. I need yer help \
right now, matey!
"""
# 定义模板中可变字段的变量信息

customer_messages = prompt_template.format_messages(
                    style=customer_style,
                    text=customer_email)
# 调用模板,对模板中的变量进行赋值,并生成最终提示语

customer_response = chat(customer_messages)
# 调用提示语,生成对话结果

通过“创建包含变量信息的提示词模板”,可以按照需求场景,灵活的通过改变变量信息,生成新的提示词。实现了模板的复用。
 

2、Output Parsers输出解析器

将大语言模型生成的结果,转换为特定结构的输出,如字典,数组等

from langchain.output_parsers import ResponseSchema
from langchain.output_parsers import StructuredOutputParser
# 加载输出解析器

gift_schema = ResponseSchema(name="gift",
                             description="Was the item purchased\
                             as a gift for someone else? \
                             Answer True if yes,\
                             False if not or unknown.")
delivery_days_schema = ResponseSchema(name="delivery_days",
                                      description="How many days\
                                      did it take for the product\
                                      to arrive? If this \
                                      information is not found,\
                                      output -1.")
price_value_schema = ResponseSchema(name="price_value",
                                    description="Extract any\
                                    sentences about the value or \
                                    price, and output them as a \
                                    comma separated Python list.")

response_schemas = [gift_schema, 
                    delivery_days_schema,
                    price_value_schema]
# 创建一组解析规则

output_parser = StructuredOutputParser.from_response_schemas(response_schemas)
format_instructions = output_parser.get_format_instructions()
#编译解析规则

review_template_2 = """\
For the following text, extract the following information:

gift: Was the item purchased as a gift for someone else? \
Answer True if yes, False if not or unknown.

delivery_days: How many days did it take for the product\
to arrive? If this information is not found, output -1.

price_value: Extract any sentences about the value or price,\
and output them as a comma separated Python list.

text: {text}

{format_instructions}
"""
# 创建一个提示词模板,将编译好的解析规则添加到模板中

prompt = ChatPromptTemplate.from_template(template=review_template_2)
messages = prompt.format_messages(text=customer_review, 
                                format_instructions=format_instructions)
# 通过模板生成提示词信息

response = chat(messages)
# 生成结果
output_dict = output_parser.parse(response.content)
# 将生成结果存入字典中

三、Memory内存组件

大语言模型在通过接口调用过程中,并不会自动记忆历史问答/上下文(来进行回答)。而通过调用memory组件。langchain提供了多种记忆历史问答/上下文的方式。

Outline概要

  • ConversationBufferMemory
  • ConversationBufferWindowMemory
  • ConversationTokenBufferMemory
  • ConversationSummaryMemory

ConversationBufferMemory对话内存

from langchain.chat_models import ChatOpenAI
from langchain.chains import ConversationChain
from langchain.memory import ConversationBufferMemory
# 加载所需包

llm = ChatOpenAI(temperature=0.0)
memory = ConversationBufferMemory()
conversation = ConversationChain(
    llm=llm, 
    memory = memory,
    verbose=True
)
# 船创建一个对话,创建一个上下文储存区,创建一个链式沟通会话。

conversation.predict(input="Hi, my name is Andrew")
conversation.predict(input="What is 1+1?")
conversation.predict(input="What is my name?")
#在会话中添加会话内容,程序会自动将提问和回答一起保存到上下文储存区

print(memory.buffer)
memory.load_memory_variables({})
#显示上下文储存区内保存的会话内容

memory.save_context({"input": "Hi"}, 
                    {"output": "What's up"})
#直接对上下文储存区内的会话内容进行赋值(赋值内容为问答对)

ConversationBufferWindowMemory有限对话内存

from langchain.memory import ConversationBufferWindowMemory
# 加载组件

memory = ConversationBufferWindowMemory(k=1)
# 添加一个只有1空间的记忆内存

memory.save_context({"input": "Hi"},
                    {"output": "What's up"})
memory.save_context({"input": "Not much, just hanging"},
                    {"output": "Cool"})
# 此时,上下文储存区里面,只有第二个对话的记忆,即在1空间情况下,程序只会记忆最新的1空间的问答记忆。

ConversationTokenBufferMemory有限词汇内存

from langchain.memory import ConversationTokenBufferMemory
from langchain.llms import OpenAI
llm = ChatOpenAI(temperature=0.0)
# 加载组件

memory = ConversationTokenBufferMemory(llm=llm, max_token_limit=30)
# 创建一个只有30词汇大小的记忆空间(因为有限空间的判断也会用到大预言模型,所以需要加载llm)

memory.save_context({"input": "AI is what?!"},
                    {"output": "Amazing!"})
memory.save_context({"input": "Backpropagation is what?"},
                    {"output": "Beautiful!"})
memory.save_context({"input": "Chatbots are what?"}, 
                    {"output": "Charming!"})
# 在这种情况下,程序只会保存不大于30个词汇的最新的问答,此时并不会强行保证问答都存在,仅包含答案也行。

memory.load_memory_variables({})
# 显示结果:{'history': 'AI: Beautiful!\nHuman: Chatbots are what?\nAI: Charming!'}

ConversationSummaryMemory总结式记忆内存

from langchain.memory import ConversationSummaryBufferMemory
# 加载包

schedule = "There is a meeting at 8am with your product team. \
You will need your powerpoint presentation prepared. \
9am-12pm have time to work on your LangChain \
project which will go quickly because Langchain is such a powerful tool. \
At Noon, lunch at the italian resturant with a customer who is driving \
from over an hour away to meet you to understand the latest in AI. \
Be sure to bring your laptop to show the latest LLM demo."
# 一个长内容

memory = ConversationSummaryBufferMemory(llm=llm, max_token_limit=100)
# 创建一个最大词汇量为100的上下文总结式记忆空间(需要大预言模型进行总结,所以加载模型)

memory.save_context({"input": "Hello"}, {"output": "What's up"})
memory.save_context({"input": "Not much, just hanging"},
                    {"output": "Cool"})
memory.save_context({"input": "What is on the schedule today?"}, 
                    {"output": f"{schedule}"})
# 添加对话

memory.load_memory_variables({})
# 显示结果为总结后的内容,通过总结将记忆内容缩短到100个词汇以内:{'history': "System: The human and AI engage in small talk before discussing the day's schedule. The AI informs the human of a morning meeting with the product team, time to work on the LangChain project, and a lunch meeting with a customer interested in the latest AI developments."}

conversation = ConversationChain(
    llm=llm, 
    memory = memory,
    verbose=True
)
conversation.predict(input="What would be a good demo to show?")
# 特别的,在对话中调用总结式记忆空间。会自动保存最新一段AI答的原文(不总结归纳)
# 并把其他对话内容进行总结。这样做可能是为了更好的获取回答,最后一段AI答价值很大,不宜信息缩减。

三、Chains对话链

Outline

  • LLMChain
  • Sequential Chains
    • SimpleSequentialChain
    • SequentialChain
  • Router Chain

LLMChain基础链

from langchain.chat_models import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
from langchain.chains import LLMChain
llm = ChatOpenAI(temperature=0.9)
# 加载包

prompt = ChatPromptTemplate.from_template(
    "What is the best name to describe \
    a company that makes {product}?"
)
# 创建一个待变量product的提示词

chain = LLMChain(llm=llm, prompt=prompt)
# 创建一个基础对话链

product = "Queen Size Sheet Set"
chain.run(product)
# 提示词变量赋值,并获得回答

SimpleSequentialChain一般序列链

一般序列链可以将前一个链的输出结果,作为后一个链的输入。一般序列链有唯一输入和输出变量。

from langchain.chains import SimpleSequentialChain
llm = ChatOpenAI(temperature=0.9)
# 加载包

first_prompt = ChatPromptTemplate.from_template(
    "What is the best name to describe \
    a company that makes {product}?"
)
# 提示词模板1,变量为product

chain_one = LLMChain(llm=llm, prompt=first_prompt)
# 链1

second_prompt = ChatPromptTemplate.from_template(
    "Write a 20 words description for the following \
    company:{company_name}"
)
# 提示词模板2,变量为company_name

chain_two = LLMChain(llm=llm, prompt=second_prompt)
# 链2

overall_simple_chain = SimpleSequentialChain(chains=[chain_one, chain_two],
                                             verbose=True)
overall_simple_chain.run(product)
# 组合链1、链2,获取结果

SequentialChain序列链

序列链中包含多个链,其中一些链的结果可以作为另一个链的输入。序列链可以支持多个输入和输出变量。

from langchain.chains import SequentialChain
llm = ChatOpenAI(temperature=0.9)
# 加载

first_prompt = ChatPromptTemplate.from_template(
    "Translate the following review to english:"
    "\n\n{Review}"
chain_one = LLMChain(llm=llm, prompt=first_prompt, 
                     output_key="English_Review"
                    )
# 链1:输入Review,输出English_Review

second_prompt = ChatPromptTemplate.from_template(
    "Can you summarize the following review in 1 sentence:"
    "\n\n{English_Review}"
)
chain_two = LLMChain(llm=llm, prompt=second_prompt, 
                     output_key="summary"
                    )
# 链2:输入English_Review,输出summary

third_prompt = ChatPromptTemplate.from_template(
    "What language is the following review:\n\n{Review}"
)
chain_three = LLMChain(llm=llm, prompt=third_prompt,
                       output_key="language"
                      )
# 链3:输入Review,输出language

fourth_prompt = ChatPromptTemplate.from_template(
    "Write a follow up response to the following "
    "summary in the specified language:"
    "\n\nSummary: {summary}\n\nLanguage: {language}"
)
chain_four = LLMChain(llm=llm, prompt=fourth_prompt,
                      output_key="followup_message"
                     )
# 链4:输入summary、language,输出followup_message

overall_chain = SequentialChain(
    chains=[chain_one, chain_two, chain_three, chain_four],
    input_variables=["Review"],
    output_variables=["English_Review", "summary","followup_message"],
    verbose=True
)
# 构建完整链,输入Review,输出"English_Review", "summary","followup_message"

overall_chain(review)

Router Chain路由链

路由链类似一个while else的函数,根据输入值,选择对应的路由(路径)进行后续的链路。整个路由链一般一个输入,一个输出。

 

physics_template = """You are a very smart physics professor. \
You are great at answering questions about physics in a concise\
and easy to understand manner. \
When you don't know the answer to a question you admit\
that you don't know.

Here is a question:
{input}"""


math_template = """You are a very good mathematician. \
You are great at answering math questions. \
You are so good because you are able to break down \
hard problems into their component parts, 
answer the component parts, and then put them together\
to answer the broader question.

Here is a question:
{input}"""

history_template = """You are a very good historian. \
You have an excellent knowledge of and understanding of people,\
events and contexts from a range of historical periods. \
You have the ability to think, reflect, debate, discuss and \
evaluate the past. You have a respect for historical evidence\
and the ability to make use of it to support your explanations \
and judgements.

Here is a question:
{input}"""


computerscience_template = """ You are a successful computer scientist.\
You have a passion for creativity, collaboration,\
forward-thinking, confidence, strong problem-solving capabilities,\
understanding of theories and algorithms, and excellent communication \
skills. You are great at answering coding questions. \
You are so good because you know how to solve a problem by \
describing the solution in imperative steps \
that a machine can easily interpret and you know how to \
choose a solution that has a good balance between \
time complexity and space complexity. 

Here is a question:
{input}"""

# 创建4种提示词模板

prompt_infos = [
    {
        "name": "physics", 
        "description": "Good for answering questions about physics", 
        "prompt_template": physics_template
    },
    {
        "name": "math", 
        "description": "Good for answering math questions", 
        "prompt_template": math_template
    },
    {
        "name": "History", 
        "description": "Good for answering history questions", 
        "prompt_template": history_template
    },
    {
        "name": "computer science", 
        "description": "Good for answering computer science questions", 
        "prompt_template": computerscience_template
    }
]
# 提示词要点信息

from langchain.chains.router import MultiPromptChain
from langchain.chains.router.llm_router import LLMRouterChain,RouterOutputParser
from langchain.prompts import PromptTemplate
llm = ChatOpenAI(temperature=0)
# 加载


destination_chains = {}
for p_info in prompt_infos:
    name = p_info["name"]
    prompt_template = p_info["prompt_template"]
    prompt = ChatPromptTemplate.from_template(template=prompt_template)
    chain = LLMChain(llm=llm, prompt=prompt)
    destination_chains[name] = chain  
    
destinations = [f"{p['name']}: {p['description']}" for p in prompt_infos]
destinations_str = "\n".join(destinations)
# 根据提示词要点信息,生成4个链,存入destination中

default_prompt = ChatPromptTemplate.from_template("{input}")
default_chain = LLMChain(llm=llm, prompt=default_prompt)
# 创建默认提示词和链

MULTI_PROMPT_ROUTER_TEMPLATE = """Given a raw text input to a \
language model select the model prompt best suited for the input. \
You will be given the names of the available prompts and a \
description of what the prompt is best suited for. \
You may also revise the original input if you think that revising\
it will ultimately lead to a better response from the language model.

<< FORMATTING >>
Return a markdown code snippet with a JSON object formatted to look like:
```json
{{{{
    "destination": string \ name of the prompt to use or "DEFAULT"
    "next_inputs": string \ a potentially modified version of the original input
}}}}
```

REMEMBER: "destination" MUST be one of the candidate prompt \
names specified below OR it can be "DEFAULT" if the input is not\
well suited for any of the candidate prompts.
REMEMBER: "next_inputs" can just be the original input \
if you don't think any modifications are needed.

<< CANDIDATE PROMPTS >>
{destinations}

<< INPUT >>
{{input}}

<< OUTPUT (remember to include the ```json)>>"""
# 创建一个提示词模板,包含destination和input两个变量

router_template = MULTI_PROMPT_ROUTER_TEMPLATE.format(
    destinations=destinations_str
)
# 提示词模板赋值destination

router_prompt = PromptTemplate(
    template=router_template,
    input_variables=["input"],
    output_parser=RouterOutputParser(),
)
# 提示词模板赋值

router_chain = LLMRouterChain.from_llm(llm, router_prompt)
chain = MultiPromptChain(router_chain=router_chain, 
                         destination_chains=destination_chains, 
                         default_chain=default_chain, verbose=True)
# 生成路由链

chain.run("xxx")

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

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

相关文章

面试大数据方向必问的问题:HDFS的读写流程

HDFS读写流程 这个问题是面试大数据分析师必不可少的问题&#xff0c;有不少面试者不能完整的说出 来&#xff0c;所以请务必记住。并且很多问题都是从 HDFS 读写流程中引申出来的。 一、HDFS读流程 Client 向 NameNode 发送 RPC 请求。请求文件 block 的位置&#xff1b;Na…

深入理解深度学习——BERT派生模型:扩大掩码范围SpanBERT

分类目录&#xff1a;《深入理解深度学习》总目录 MLM训练方法是BERT拥有自然语言理解能力的核心训练方法。然而&#xff0c;BERT在预训练过程中挑选掩码词的概率是独立计算的&#xff0c;即BERT掩码词的粒度是最小的&#xff0c;可能是单个词&#xff0c;也可能是一个词的部分…

【连载】经历了十多年的电子开发,回过头来跟大家一起,看穿单片机!

「经历了十多年的单片机开发&#xff0c;站在我现在的高度来回看单片机&#xff0c;可谓望眼欲穿。」 下面振南要介绍的是“单片机的体系架构模型”&#xff0c;是超脱于任何一种具体型号的单片机芯片之上的&#xff08;我感觉我要成仙&#xff09;&#xff0c;它具有很强的普适…

【Django】图形验证码显示及验证

图形验证码显示及验证 开发项目时&#xff0c;在登陆或者注册功能中为防止脚本恶意破坏系统&#xff0c;故而添加图形验证码。 文章目录 图形验证码显示及验证1 安装配置2 验证码显示及正确性验证3 效果显示 1 安装配置 安装第三方库 pip install django-simple-captcha配置s…

SpringBoot+Vue 的在线考试系统(附源码,数据库,教程)

文章目录 源码下载地址第一章第二章.主要技术第三章第四章 系统设计4.1功能结构4.2 数据库设计4.2.1 数据库E/R图4.2.2 数据库表 第五章 系统功能实现5.1系统登录注册5.2管理员功能模块 源码下载地址 源码下载地址 源码下载地址https://download.csdn.net/download/u013749113…

[python][yolov8][深度学习]将yolov8实例分割成一个类几句代码完成实例分割任务

大家都知道,yolov8目前支持图像分类、目标检测、姿态估计、实例分割&#xff0c;而实例分割一般都是用命令行去预测图片&#xff0c;这个如果要引入pyqt5或着嵌入其他python模块有点麻烦&#xff0c;因此需要封装一个类去预测图像&#xff0c;这样我们可以轻松完成各种实例分割…

Redis实战案例4-缓存更新策略

1. 缓存更新策略 缓存中的数据一致性问题&#xff08;数据库更新数据&#xff0c;而Redis存的是旧数据&#xff09; 内存淘汰策略&#xff1a;当内存很充足时&#xff0c;很长时间无法淘汰数据&#xff0c;所以很难控制淘汰&#xff0c;一致性差&#xff1b; 超时剔除&#xff…

【教学类-36】Midjounery生成的四张图片切片成四张小图

作品展示&#xff1a; 把一张正方形图片的四个等大小图切割成四张图片 背景需求 最近在学习ChatGPT的绘画&#xff08;midjounery AI艺术&#xff09; 我想给中班孩子找卡通动物图片&#xff08;黑白边框&#xff09;&#xff0c;打印下来&#xff0c;孩子们练习描边、涂色…

C++11-右值引用与移动语义

右值引用与移动语义 一&#xff0c;右值引用概念右值引用简单例子左值引用与右值引用的比较 二&#xff0c;右值引用的使用场景函数对于其内部局部对象的传值返回insert&#xff0c;push等接口左值引用与右值引用总结 三&#xff0c;完美转发四&#xff0c;新的类功能默认成员函…

【数据分享】1929-2022年全球站点的逐月平均海平面压力数据(Shp\Excel\12000个站点)

气象数据是在各项研究中都经常使用的数据&#xff0c;气象指标包括气温、风速、降水、能见度等指标&#xff0c;说到气象数据&#xff0c;最详细的气象数据是具体到气象监测站点的数据&#xff01; 对于具体到监测站点的气象数据&#xff0c;之前我们分享过1929-2022年全球气象…

机器学习小结之决策树

文章目录 前言一、介绍1.1 原理1.2 流程1.3 信息熵&#xff0c;信息增益和基尼不纯度 二、构建决策树2.1 特征选择2.2 决策树生成2.3 剪枝 三、经典算法3.1 ID33.2 C4.53.3 CART 四、案例4.1 Iris 数据集 鸢尾花 分类4.2 基于决策树的英雄联盟游戏胜负预测 参考 前言 决策树(D…

GDPU 模电(电工) 作业答案

&#x1f351; 配套资源 &#x1f4da; 电子技术基础&#xff1a;电路与模拟电子[第2版] 提取码: 345r 第2章 电阻电路分析 第4章 正弦稳态电路分析 第6章 半导体器件 第7章 放大电路分析 第8章 负反馈放大电路 第9章 集成运算放大器及其应用 第11章 直流稳压电源 &#x1f6…

深度学习(10)之Roboflow 使用详解:数据集标注、训练 及 下载

Roboflow 使用详解&#xff1a;数据集标注、训练 及 下载 本文在 用YOLOv8推荐的Roboflow工具来训练自己的数据集 的基础上进行了修改 介绍如何从网站下载开源数据集详细介绍如何借助 roboflow 标注数据集并自动转换为可直接训练的数据格式 获取开源数据集 跳转找到开源分页…

浅谈Spring Cloud Gateway

网关:用户和微服务的桥梁 网关的核心是一组过滤器&#xff0c;按照先后顺序执行过滤操作。 Spring Cloud Gateway是基于webFlux框架实现&#xff0c;而webFlux框架底层则使用了高性能的Reactor模式通信框架的Netty Spring Cloud Gateway是Spring Cloud生态系统中的一个API网…

leetcode62. 不同路径(动态规划-java)

不同路径 leetcode62. 不同路径题目描述暴力递归代码演示 递归加缓存代码演示 动态规划代码演示 动态规划专题 leetcode62. 不同路径 来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 链接&#xff1a;https://leetcode.cn/problems/unique-paths 题目描述 一个机器人位…

leetcode863. 二叉树中所有距离为 K 的结点(java)

二叉树中所有距离为 K 的结点 leetcode863. 二叉树中所有距离为 K 的结点题目描述 DFS 深度优先遍历代码演示 二叉树专题 leetcode863. 二叉树中所有距离为 K 的结点 来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 链接&#xff1a;https://leetcode.cn/problems/all-…

英之剑法——第一境(通达人与物之境)

&#x1f31f;博主&#xff1a;命运之光 ☀️专栏&#xff1a;英之剑法&#x1f5e1; ❤️‍&#x1f525;专栏&#xff1a;英之试炼&#x1f525; ☀️博主的其他文章&#xff1a;点击进入博主的主页 &#x1f433; 开篇想说的话&#xff1a;开学就大三了&#xff0c;命运之光…

永磁同步电机在线参数辨识综述

优点 实时性&#xff1a;在线参数辨识能够在电机实际运行时进行参数估计&#xff0c;可以实时地获取电机的参数信息。这使得在线参数辨识更适用于需要实时调节和优化电机控制策略的应用场景。 动态适应性&#xff1a;在线参数辨识可以根据电机的实时工作状态和环境变化来动态地…

最“赚钱”编程语言出炉,惊到我了.....

Stack Overflow 发布了 2023 年开发者调查报告&#xff0c;据称共计超过 9 万名开发者参与了此次调查。 完整报告包含了受访开发者画像&#xff0c;以及关于开发技术、AI、职业、社区等方面的内容。本文主要介绍关于开发技术和 AI 的部分。 懒人目录&#xff1a; 最流行编程语…

[皮尔逊相关系数corrwith]使用案例:电影推荐系统

协同过滤算法用于发现用户与物品之间的相关性&#xff0c;主要有两种&#xff1a;基于用户的和基于物品的。 基于用户&#xff1a; 用户1购买了物品A、B、C、D&#xff0c;并给了好评&#xff1b;而用户2也买了A、B、C&#xff0c;那么认为用户1和用户2是同类型用户&#xff…