如果有重复的就当复习好了,后面回答问题都带点示例或伪代码
问题 21 LangChain 中的 Output Parsers 是什么?它们如何帮助解析大语言模型(LLM)的输出?
Output Parsers 是 LangChain 提供的一种工具,用于将大语言模型(LLM)生成的输出结果解析成结构化或指定格式的数据。这在需要对 LLM 输出进行进一步处理或集成到其他系统时非常有用。
Output Parsers 的作用
1.格式化输出:
将 LLM 的文本输出转换成所需的结构化格式,如 JSON、字典或特定的字符串格式。
2.结果解析:
自动提取关键信息,例如用户指令中的数据值、标签或实体。
3.错误处理:
提供验证和纠错机制,确保输出符合预期格式。
问题 22 如何在 LangChain 中使用 Callbacks 进行日志记录和监控?请描述具体实现方式。
在 LangChain 中,可以使用 Callbacks 来实现日志记录和监控。Callbacks 允许在链或模型执行过程中捕获事件并进行自定义处理,如记录日志、监控性能等。
实现步骤
-
导入相关库
- 导入
BaseCallbackHandler
以自定义回调。
from langchain.callbacks.base import BaseCallbackHandler from langchain.schema import LLMResult
- 导入
-
自定义回调类
- 继承
BaseCallbackHandler
并重写所需的回调方法,如on_llm_start
、on_llm_end
等。
class LoggingCallbackHandler(BaseCallbackHandler): def on_llm_start(self, serialized, prompts, **kwargs): print(f"LLM 开始: {prompts}") def on_llm_end(self, response: LLMResult, **kwargs): print(f"LLM 结束: {response.generations}") def on_chain_end(self, outputs, **kwargs): print(f"链结束: {outputs}")
- 继承
-
将回调传入链或 LLM
- 在初始化链或 LLM 时,将自定义回调添加到
callbacks
参数。
from langchain.llms import OpenAI llm = OpenAI(model="text-davinci-003", callbacks=[LoggingCallbackHandler()]) response = llm("告诉我一个笑话") print(response)
- 在初始化链或 LLM 时,将自定义回调添加到
-
监控和日志记录
- 运行链或 LLM 时,回调会自动捕获事件,打印或记录日志。
主要回调方法
on_llm_start
: LLM 开始调用时触发。on_llm_end
: LLM 调用结束时触发。on_chain_start
: 链开始执行时触发。on_chain_end
: 链执行结束时触发。on_tool_start
: 工具开始执行时触发。on_tool_end
: 工具结束时触发。
问题 23 如何在 LangChain 中实现和配置 记忆(Memory) 功能,以保持对话的上下文和状态?请描述具体实现步骤。
在 LangChain 中实现和配置 记忆(Memory) 功能,以保持对话的上下文和状态,可以按照以下步骤进行:
-
导入相关库
from langchain.memory import ConversationBufferMemory from langchain.llms import OpenAI from langchain.chains import ConversationChain
-
初始化记忆模块
使用ConversationBufferMemory
来存储对话历史。memory = ConversationBufferMemory()
-
配置 LLM 和链
将记忆模块传递给链,以便在每次对话中维护上下文。llm = OpenAI(model="gpt-3.5-turbo") conversation = ConversationChain(llm=llm, memory=memory)
-
进行对话
每次调用链时,记忆模块会自动更新对话状态。response = conversation.run("你好,今天的天气如何?") print(response) response = conversation.run("明天我应该带伞吗?") print(response)
-
自定义记忆(可选)
可以根据需要选择不同类型的记忆模块,如ConversationSummaryMemory
,并配置相关参数以优化性能和存储。
通过上述步骤,LangChain 的记忆功能能够有效地跟踪和管理对话上下文,使得多轮对话更加连贯和智能。
问题 24 如何在 LangChain 中使用 提示模板(Prompt Templates) 来定制模型的输入和输出?请描述具体实现步骤。
在 LangChain 中,提示模板(Prompt Templates) 用于定制和优化模型的输入输出,使其更符合特定的应用需求。以下是具体的实现步骤:
实现步骤
-
导入相关库
from langchain import PromptTemplate from langchain.llms import OpenAI from langchain.chains import LLMChain
-
创建提示模板
使用PromptTemplate
定义输入变量和模板内容。template = """ 你是一个专业的客服代表。根据以下客户问题,提供详细且友好的回答。 客户问题: {customer_question} 回答: """ prompt = PromptTemplate( input_variables=["customer_question"], template=template )
-
初始化语言模型
配置所需的语言模型,例如 OpenAI 的 GPT-3。llm = OpenAI(model="gpt-3.5-turbo")
-
创建链
将提示模板和语言模型结合,创建一个LLMChain
。chain = LLMChain(llm=llm, prompt=prompt)
-
运行链并生成响应
传入具体的输入变量,获取模型生成的回答。customer_question = "我的订单什么时候能到?" response = chain.run(customer_question=customer_question) print(response)
问题 25 如何在 LangChain 中使用 Agents 来实现复杂的任务自动化?请描述具体实现步骤。
在 LangChain 中,Agents 允许模型自主决策使用不同的工具(如搜索、计算等)来完成复杂任务。通过Agents,可以构建更智能和灵活的应用。以下是具体的实现步骤:
实现步骤
-
导入相关库
from langchain.agents import AgentExecutor, Tool, initialize_agent, load_tools from langchain.llms import OpenAI
-
定义工具(Tools)
工具是Agents可以调用的功能模块,如搜索引擎、计算器等。tools = load_tools(["serpapi", "calculator"])
-
初始化语言模型
配置所需的语言模型,例如 OpenAI 的 GPT-3。llm = OpenAI(model="gpt-3.5-turbo")
-
创建Agent
使用initialize_agent
将工具和语言模型结合,指定Agent类型(如“zero-shot-react-description”)。agent = initialize_agent(tools, llm, agent="zero-shot-react-description", verbose=True)
-
执行任务
向Agent提供输入,Agent会自主决定调用哪些工具来完成任务。response = agent.run("帮我查一下纽约今天的天气,并计算明天的温度比今天高多少度。") print(response)
详细说明
- 工具加载:使用
load_tools
可以快速加载预定义的工具集,或者自定义工具。 - Agent类型:不同的Agent类型(如“zero-shot-react-description”、“conversational-react-description”)适用于不同的应用场景,选择合适的类型可以优化性能。
- 决策过程:Agent基于输入和可用工具,动态决定调用哪些工具以及调用的顺序,以实现复杂任务的自动化。
示例代码
from langchain.agents import initialize_agent, load_tools
from langchain.llms import OpenAI
# 加载工具
tools = load_tools(["serpapi", "calculator"])
# 初始化语言模型
llm = OpenAI(model="gpt-3.5-turbo")
# 创建Agent
agent = initialize_agent(tools, llm, agent="zero-shot-react-description", verbose=True)
# 执行任务
response = agent.run("帮我查一下纽约今天的天气,并计算明天的温度比今天高多少度。")
print(response)
问题 26 如何在 LangChain 中集成 向量存储(Vector Stores) 来实现高效的语义搜索?请描述具体实现步骤。
在 LangChain 中,集成 向量存储(Vector Stores) 可以显著提升语义搜索的效率和准确性。以下是具体的实现步骤:
实现步骤
-
导入相关库
from langchain.vectorstores import FAISS from langchain.embeddings import OpenAIEmbeddings from langchain.llms import OpenAI from langchain.chains import VectorDBQA
-
初始化嵌入模型
使用OpenAIEmbeddings
或其他支持的嵌入模型来生成文本的向量表示。embeddings = OpenAIEmbeddings()
-
准备文档数据
收集并预处理需要进行语义搜索的文档或数据集。documents = [ "LangChain 是一个用于构建应用的框架。", "向量存储可以提高搜索的效率。", "语义搜索能够理解自然语言的含义。" ]
-
创建向量存储实例
使用 FAISS 或其他支持的向量存储库来存储文档的向量。vector_store = FAISS.from_texts(documents, embeddings)
-
配置语言模型
设置所需的语言模型,例如 OpenAI 的 GPT-3。llm = OpenAI(model="gpt-3.5-turbo")
-
创建问答链
使用VectorDBQA
链将向量存储与语言模型结合,实现语义搜索问答功能。qa_chain = VectorDBQA.from_chain_type( llm=llm, chain_type="stuff", vectorstore=vector_store, return_source_documents=True )
-
执行语义搜索
向问答链提供查询,获取相关的答案和来源文档。query = "什么是向量存储?" result = qa_chain({"query": query}) print("回答:", result['result']) print("来源文档:", result['source_documents'])
详细说明
-
向量存储选择:FAISS 是一种高效的相似性搜索库,适用于大规模向量数据。根据需求,也可以选择 Pinecone、Weaviate 等其他向量存储服务。
-
嵌入模型:嵌入模型将文本转换为向量表示,是实现语义搜索的关键。确保选择适合任务的嵌入模型以获得最佳效果。
-
问答链配置:
VectorDBQA
链结合了向量存储和语言模型,能够在查询时检索相关文档并生成准确的回答。
问题 27 如何在 LangChain 中集成外部 API 或数据源?请描述具体实现步骤。
在 LangChain 中集成外部 API 或数据源,可以扩展应用的功能,使其能够访问和利用外部信息。以下是具体的实现步骤:
实现步骤
-
导入相关库
from langchain.agents import initialize_agent, load_tools from langchain.llms import OpenAI from langchain.tools import BaseTool import requests
-
创建自定义工具(Tool)
定义一个自定义工具,用于调用外部 API。例如,调用天气 API 获取天气信息。class WeatherTool(BaseTool): name = "weather" description = "获取指定城市的当前天气信息。输入为城市名称。" def _run(self, city: str): api_key = "YOUR_WEATHER_API_KEY" url = f"http://api.weatherapi.com/v1/current.json?key={api_key}&q={city}&lang=zh" response = requests.get(url) if response.status_code == 200: data = response.json() return f"{city} 的当前天气是 {data['current']['condition']['text']},温度为 {data['current']['temp_c']}°C。" else: return "无法获取天气信息,请稍后再试。" async def _arun(self, city: str): raise NotImplementedError("异步运行尚未实现。")
-
加载工具
将自定义工具添加到工具列表中。tools = load_tools(["weather"]) # 假设已经定义了 "weather" 工具 # 或者手动添加自定义工具 tools = [WeatherTool()]
-
初始化语言模型
配置所需的语言模型,例如 OpenAI 的 GPT-3。llm = OpenAI(model="gpt-3.5-turbo")
-
创建 Agent
使用initialize_agent
将工具和语言模型结合,指定 Agent 类型。agent = initialize_agent(tools, llm, agent="zero-shot-react-description", verbose=True)
-
执行任务
向 Agent 提供输入,Agent 会根据需要调用外部 API。query = "请告诉我北京的当前天气。" response = agent.run(query) print(response)
详细说明
-
自定义工具:通过继承
BaseTool
,可以创建自定义工具来调用任何外部 API 或数据源。工具需要定义name
、description
以及_run
方法。 -
工具加载:使用
load_tools
可以加载预定义的工具,也可以手动添加自定义工具到工具列表中。 -
Agent 配置:选择合适的 Agent 类型(如“zero-shot-react-description”)能够优化工具的调用和任务执行效率。
-
错误处理:在自定义工具中,应包含对 API 调用失败的处理逻辑,以确保应用的稳定性。
示例代码
from langchain.agents import initialize_agent, load_tools
from langchain.llms import OpenAI
from langchain.tools import BaseTool
import requests
class WeatherTool(BaseTool):
name = "weather"
description = "获取指定城市的当前天气信息。输入为城市名称。"
def _run(self, city: str):
api_key = "YOUR_WEATHER_API_KEY"
url = f"http://api.weatherapi.com/v1/current.json?key={api_key}&q={city}&lang=zh"
response = requests.get(url)
if response.status_code == 200:
data = response.json()
return f"{city} 的当前天气是 {data['current']['condition']['text']},温度为 {data['current']['temp_c']}°C。"
else:
return "无法获取天气信息,请稍后再试。"
async def _arun(self, city: str):
raise NotImplementedError("异步运行尚未实现。")
# 加载自定义工具
tools = [WeatherTool()]
# 初始化语言模型
llm = OpenAI(model="gpt-3.5-turbo")
# 创建 Agent
agent = initialize_agent(tools, llm, agent="zero-shot-react-description", verbose=True)
# 执行任务
query = "请告诉我上海的当前天气。"
response = agent.run(query)
print(response)
问题 28 如何在 LangChain 中进行链的调试和测试?请描述具体实现步骤。
在 LangChain 中,进行链的调试和测试是确保应用正常运行和满足预期功能的重要步骤。以下是具体的实现步骤:
实现步骤
-
启用详细日志
- 在初始化链或模型时,设置
verbose=True
以输出详细的执行日志,帮助识别问题所在。
from langchain.llms import OpenAI from langchain.chains import ConversationChain llm = OpenAI(model="gpt-3.5-turbo", verbose=True) conversation = ConversationChain(llm=llm, verbose=True)
- 在初始化链或模型时,设置
-
使用回调(Callbacks)
- 利用 Callbacks 捕获链执行过程中的关键事件,记录中间状态和输出,便于分析和调试。
from langchain.callbacks.base import BaseCallbackHandler class DebugCallbackHandler(BaseCallbackHandler): def on_llm_start(self, serialized, prompts, **kwargs): print("LLM 开始执行") def on_llm_end(self, response, **kwargs): print("LLM 执行结束,响应内容:", response) def on_chain_start(self, serialized, inputs, **kwargs): print("链开始执行,输入参数:", inputs) def on_chain_end(self, outputs, **kwargs): print("链执行结束,输出结果:", outputs) callbacks = [DebugCallbackHandler()] conversation = ConversationChain(llm=llm, callbacks=callbacks, verbose=True)
-
单元测试
- 编写单元测试来验证链的各个组件是否按预期工作。使用
unittest
或pytest
等测试框架进行测试。
import unittest class TestConversationChain(unittest.TestCase): def test_conversation_response(self): response = conversation.run("你好,今天的天气如何?") self.assertIsNotNone(response) self.assertIn("天气", response) if __name__ == '__main__': unittest.main()
- 编写单元测试来验证链的各个组件是否按预期工作。使用
-
模拟输入输出
- 使用模拟(Mock)技术来测试链在特定输入下的行为,确保其对不同场景的处理正确。
from unittest.mock import patch @patch('langchain.llms.OpenAI.generate') def test_mock_llm_response(mock_generate): mock_generate.return_value = "这是一个模拟的响应。" response = conversation.run("请给我一个笑话。") assert response == "这是一个模拟的响应。"
-
性能监控
- 监控链的执行时间和资源消耗,识别潜在的性能瓶颈。可以使用 Python 的
time
模块或更高级的性能分析工具。
import time start_time = time.time() response = conversation.run("帮我总结一下这篇文章。") end_time = time.time() print(f"执行时间: {end_time - start_time} 秒")
- 监控链的执行时间和资源消耗,识别潜在的性能瓶颈。可以使用 Python 的
-
错误处理
- 实现健壮的错误处理机制,捕获并记录链执行过程中可能出现的异常,确保应用的稳定性。
try: response = conversation.run("请告诉我一个不存在的命令。") except Exception as e: print(f"发生错误: {e}")
详细说明
-
详细日志:通过启用
verbose
参数,可以实时查看链和模型的执行过程,帮助快速定位问题。 -
回调:自定义回调处理器能够在链执行的不同阶段插入自定义逻辑,如日志记录、错误处理等,增强调试能力。
-
单元测试:编写针对性的测试用例,确保链的各个部分在不同输入下表现一致,提升代码质量和可靠性。
-
模拟输入输出:通过模拟外部依赖(如 LLM 的响应),可以在隔离的环境中测试链的逻辑,避免外部因素干扰。
-
性能监控:监控链的执行效率,优化性能,确保应用在生产环境中的响应速度和资源利用率。
-
错误处理:捕获并妥善处理运行时错误,防止应用因未处理的异常而崩溃,提升用户体验。
问题 29 如何在 LangChain 中部署应用到生产环境?请描述具体实现步骤。
将 LangChain 应用部署到生产环境涉及多个步骤,包括准备环境、选择部署平台、配置安全性以及监控应用性能。以下是具体的实现步骤:
实现步骤
-
准备环境
- 代码优化:确保代码经过优化,去除调试信息和不必要的依赖。
- 环境管理:使用虚拟环境(如
venv
或conda
)管理依赖,确保一致性。 - 配置文件:将敏感信息(如 API 密钥)存储在环境变量或安全的配置文件中,避免硬编码。
-
选择部署平台
- 云服务提供商:选择合适的云平台,如 AWS、GCP、Azure,或者使用专门的 PaaS 服务如 Heroku、Vercel。
- 容器化:使用 Docker 将应用容器化,确保在不同环境中的一致性。
FROM python:3.9-slim WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY . . CMD ["python", "app.py"]
- 编排工具:对于复杂应用,使用 Kubernetes 进行容器编排,管理扩展和负载均衡。
-
部署应用
- 容器部署:将 Docker 镜像推送到容器注册中心(如 Docker Hub),然后在目标平台上拉取并运行。
docker build -t your-username/langchain-app . docker push your-username/langchain-app docker run -d -p 80:80 your-username/langchain-app
- 无服务器架构:利用 AWS Lambda 或 Google Cloud Functions 部署无服务器应用,适合轻量级和事件驱动的任务。
- 容器部署:将 Docker 镜像推送到容器注册中心(如 Docker Hub),然后在目标平台上拉取并运行。
-
配置安全性
- HTTPS:配置 SSL/TLS 证书,确保数据传输的安全性。可以使用 Let’s Encrypt 获取免费证书。
- 身份验证与授权:实现用户认证(如 OAuth 2.0)和访问控制,保护应用资源。
- 防火墙与网络安全:配置防火墙规则,限制不必要的端口访问,确保网络安全。
-
监控与日志记录
- 监控工具:使用 Prometheus、Grafana 或云服务自带的监控工具,实时监控应用性能和健康状态。
- 日志管理:集成日志管理系统,如 ELK Stack(Elasticsearch, Logstash, Kibana)或云服务的日志解决方案,便于故障排查和性能分析。
-
持续集成与持续部署(CI/CD)
- CI/CD 工具:配置 GitHub Actions、GitLab CI 或 Jenkins,实现代码的自动测试和部署。
- 自动化流程:每次代码提交后,自动运行测试用例,若通过则自动部署到生产环境。
-
性能优化
- 负载均衡:使用负载均衡器(如 AWS ELB)分发流量,提升应用的可用性和响应速度。
- 缓存机制:引入缓存(如 Redis)减少重复计算,提高响应效率。
- 数据库优化:根据需要选择合适的数据库方案,并进行索引优化和查询优化。
示例代码
以下是一个简单的 Flask 应用 Docker 化并部署的示例:
# app.py
from flask import Flask, request, jsonify
from langchain.llms import OpenAI
app = Flask(__name__)
llm = OpenAI(model="gpt-3.5-turbo")
@app.route('/generate', methods=['POST'])
def generate():
data = request.json
prompt = data.get('prompt', '')
response = llm(prompt)
return jsonify({"response": response})
if __name__ == '__main__':
app.run(host='0.0.0.0', port=80)
# Dockerfile
FROM python:3.9-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["python", "app.py"]
问题 30 如何在 LangChain 中集成 数据库 以实现数据驱动的应用?请描述具体实现步骤。
在 LangChain 中集成 数据库 能够增强应用的数据访问能力,使其能够根据存储在数据库中的信息生成更精准和相关的响应。以下是具体的实现步骤:
实现步骤
-
选择合适的数据库
- 根据应用需求选择合适的数据库类型,如关系型数据库(PostgreSQL、MySQL)或NoSQL数据库(MongoDB)。
- 确保数据库能够存储和检索应用所需的数据格式。
-
安装必要的库
- 安装用于连接和操作数据库的Python库。例如,使用
SQLAlchemy
连接关系型数据库,或使用pymongo
连接MongoDB。
pip install sqlalchemy pymongo
- 安装用于连接和操作数据库的Python库。例如,使用
-
配置数据库连接
- 设置数据库连接字符串,并初始化数据库连接。
# 使用 SQLAlchemy 连接 PostgreSQL 示例 from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker DATABASE_URL = "postgresql://user:password@localhost:5432/mydatabase" engine = create_engine(DATABASE_URL) SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) session = SessionLocal()
-
定义数据模型
- 使用 ORM(对象关系映射)工具定义数据库中的数据模型。
from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column, Integer, String Base = declarative_base() class Product(Base): __tablename__ = "products" id = Column(Integer, primary_key=True, index=True) name = Column(String, index=True) description = Column(String) price = Column(Integer)
-
集成数据库查询到 LangChain
- 创建自定义工具(Tool),用于从数据库中检索数据,并将其集成到 LangChain 的 Agent 中。
from langchain.tools import BaseTool class DatabaseQueryTool(BaseTool): name = "database_query" description = "用于从产品数据库中检索产品信息。输入为产品名称。" def _run(self, product_name: str): product = session.query(Product).filter(Product.name.ilike(f"%{product_name}%")).first() if product: return f"产品名称: {product.name}\n描述: {product.description}\n价格: {product.price}元" else: return "未找到相关产品信息。" async def _arun(self, product_name: str): raise NotImplementedError("异步运行尚未实现。")
-
加载并初始化工具
- 将自定义的数据库查询工具加载到工具列表中,并初始化 Agent。
from langchain.agents import initialize_agent from langchain.llms import OpenAI tools = [DatabaseQueryTool()] llm = OpenAI(model="gpt-3.5-turbo") agent = initialize_agent(tools, llm, agent="zero-shot-react-description", verbose=True)
-
执行查询
- 向 Agent 提出查询,Agent 将调用数据库工具获取相关数据并生成响应。
query = "请告诉我关于iPhone 14的详细信息。" response = agent.run(query) print(response)
详细说明
-
自定义工具:通过继承
BaseTool
,可以创建自定义工具来执行特定的数据库查询操作。这些工具可以被 Agent 调用,以增强其数据访问能力。 -
工具描述:在定义工具时,提供清晰的
description
有助于 Agent 理解何时以及如何使用该工具。 -
数据库优化:确保数据库索引的合理设置,以提高查询性能,特别是在处理大量数据时。
-
安全性考虑:妥善管理数据库凭证,避免将敏感信息硬编码在代码中。可以使用环境变量或秘密管理服务来存储数据库连接信息。
示例代码
以下是一个完整的示例,展示如何将 PostgreSQL 数据库与 LangChain 集成:
# database.py
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
DATABASE_URL = "postgresql://user:password@localhost:5432/mydatabase"
engine = create_engine(DATABASE_URL)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
session = SessionLocal()
Base = declarative_base()
class Product(Base):
__tablename__ = "products"
id = Column(Integer, primary_key=True, index=True)
name = Column(String, index=True)
description = Column(String)
price = Column(Integer)
# 创建表(仅首次运行时需要)
# Base.metadata.create_all(bind=engine)
# tools.py
from langchain.tools import BaseTool
from database import session, Product
class DatabaseQueryTool(BaseTool):
name = "database_query"
description = "用于从产品数据库中检索产品信息。输入为产品名称。"
def _run(self, product_name: str):
product = session.query(Product).filter(Product.name.ilike(f"%{product_name}%")).first()
if product:
return f"产品名称: {product.name}\n描述: {product.description}\n价格: {product.price}元"
else:
return "未找到相关产品信息。"
async def _arun(self, product_name: str):
raise NotImplementedError("异步运行尚未实现。")
# app.py
from langchain.agents import initialize_agent
from langchain.llms import OpenAI
from tools import DatabaseQueryTool
def main():
tools = [DatabaseQueryTool()]
llm = OpenAI(model="gpt-3.5-turbo")
agent = initialize_agent(tools, llm, agent="zero-shot-react-description", verbose=True)
query = "请告诉我关于iPhone 14的详细信息。"
response = agent.run(query)
print(response)
if __name__ == "__main__":
main()
总结
通过在 LangChain 中集成 数据库,可以显著提升应用的数据处理能力,实现更加智能和数据驱动的功能。自定义工具使得 LangChain 能够灵活地访问和操作数据库中的信息,从而生成更为精准和相关的响应。掌握数据库集成的方法,有助于开发者构建功能强大且具有高度定制化的智能应用。