2024年8月

《数据资产管理核心技术与应用》是清华大学出版社出版的一本图书,全书共分10章,第1章主要让读者认识数据资产,了解数据资产相关的基础概念,以及数据资产的发展情况。第2~8章主要介绍大数据时代数据资产管理所涉及的核心技术,内容包括元数据的采集与存储、数据血缘、数据质量、数据监控与告警、数据服务、数据权限与安全、数据资产管理架构等。第9~10章主要从实战的角度介绍数据资产管理技术的应用实践,包括如何对元数据进行管理以发挥出数据资产的更大潜力,以及如何对数据进行建模以挖掘出数据中更大的价值。

图书介绍:
数据资产管理核心技术与应用

今天主要是给大家分享一下第三章的内容:

第三章的标题为数据血缘

内容思维导图如下:

1、获取数据血缘的技术实现

1.1、如何从Hive中获取数据血缘

Hive 是典型的数据仓库的代表,也是大数据中离线数据分层模型设计的代表,并且支持HQL的数据处理和计算,所以Hive为了方便用户做数据跟踪,在底层设计时,其实就考虑到了数据血缘跟踪这个问题。Hive 自身的血缘在其源码中主要通过org.apache.hadoop.hive.ql.hooks.LineageLogger.java 来输出,org.apache.hadoop.hive.ql.hooks.LineageLogger.java代码中主要处理的过程如下图所示,血缘主要通过edges(DAG图的流向)和vertices(DAG图的节点)来进行输出。《数据资产管理核心技术与应用》读书笔记

在org.apache.hadoop.hive.ql.hooks.LineageLogger.java的源码中定义了其支持的4种SQL操作类型,分别为QUERY(查询)、CREATETABLE_AS_SELECT(将Select 查询创建为一张表)、ALTERVIEW_AS(修改视图)、CREATEVIEW(创建视图)。

org.apache.hadoop.hive.ql.hooks.LineageLogger.java在解析和生成edges(DAG图的流向)和vertices(DAG图的节点)信息时,会判断QueryPlan(查询计划)的类型是否是支持的4种SQL操作类型中的一种,如果不是的话,就不会解析和生成edges和vertices。

org.apache.hadoop.hive.ql.hooks.Hook.java是Hive提供的Hook(钩子)功能,用于在Hive 任务执行前或者执行后,注入自定义的的操作代码。

具体的代码实现,可以直接参考纸质书,这里不再赘述。

1.2、 从Spark 执行计划中获取数据血缘

Spark底层生成执行计划以及处理执行计划的过程如下图所示。

从图中可以看到,

1、 执行SQL语句或者Data Frame时,会先生成一个Unresolved Logical Plan,就是没有做过任何处理和分析的逻辑执行计划,仅仅会从SQL语法的角度做一些基础性的校验。

2、 之后通过获取Catalog的数据,对需要执行的SQL语句做表名、列名的进一步分析校验,从而生成一个可以直接运行的逻辑执行计划。

3、 但是Spark底层会有个优化器来生成一个最优的执行操作方式,从而生成一个优化后的最佳逻辑执行计划。

4、 将最终确定下来的逻辑执行计划转换为物理执行计划,转换为最终的代码进行执行。

Spark的执行计划其实就是数据处理的过程计划,会将SQL语句或者DataFrame 做解析,并且结合Catalog一起,生成最终数据转换和处理的代码。所以可以从Spark的执行计划中,获取到数据的转换逻辑,从而解析到数据的血缘。但是spark的执行计划都是在spark底层内部自动处理的,如何获取到每次Spark任务的执行计划的信息呢?其实在Spark底层有一套Listener的架构设计,可以通过Spark Listener 来获取到spark 底层很多执行的数据信息。

在spark的源码中,以Scala的形式提供了一个org.apache.spark.sql.util.QueryExecutionListener  trait (类似Java 语言的接口),来作为Spark SQL等任务执行的监听器。在org.apache.spark.sql.util.QueryExecutionListener  中提供了如下表所示的两个方法。《数据资产管理核心技术与应用》读书笔记

方法名

描述

def onSuccess(funcName: String, qe: QueryExecution, durationNs: Long): Unit

执行成功时,调用的方法,其中包括了执行计划参数,这里的执行计划可以是逻辑计划或者物理计划

def onFailure(funcName: String, qe: QueryExecution, exception: Exception): Unit

执行失败时,调用的方法,其中同样也包括了执行计划参数,这里的执行计划可以是逻辑计划或者物理计划

因此可以借用QueryExecutionListener  来主动让Spark在执行任务时,将执行计划信息推送到自己的系统或者数据库中,然后再做进一步的解析,如下图

具体的代码实现,由于代码较多,请参考纸质书。

1.3、 从Spark  SQL语句中获取数据血缘

在Spark任务处理中,通过SQL语句来实现离线的ETL 数据处理是其在大数据中最常见的应用方式,如下图所示针对这种应用场景,可以直接通过获取Spark 中运行的SQL语句,然后通过解析SQL语句,并且结合Catalog,来分析出SQL 语句中包含的输入表和输出表的数据血缘关系。《数据资产管理核心技术与应用》读书笔记

有了通过SQL语句来解析血缘的思路后,需要解决的问题就是怎么自动抓取到Spark中运行的SQL语句。在上面的叙述中,有提到过Spark 有Listener的机制,org.apache.spark.sql.util.QueryExecutionListener只是Listener中的一种,可以通过Listener的方式自动获取到Spark的相关执行信息。在Spark中提供了org.apache.spark.scheduler.SparkListener这个底层抽象类来供上层代码监听Spark在整个生命执行周期中的相关事件消息,如下图所示。

获取Spark 执行的SQL 语句的整体流程总结如下图

具体的代码实现,由于代码较多,请参考纸质书。

1.4、 从Flink中获取数据血缘

FlinkSQL 在底层执行时,大概包含了如下的5个步骤,其底层执行过程和SparkSQL非常的类似。

  • 第一步:对即将执行的SQL语句做语法分析,此时会通过Apache Calcite 将SQL语句直接转换为AST (Abstract Syntax Tree的简写,翻译过来就是抽象语法树),也就是Calcite 中的SqlNode节点树。Calcite是一个开源的SQL解析工具,Flink在底层技术实现时,集成了Calcite作为其底层的SQL语句解析器, Calcite的Github 地址为https://github.com/apache/calcite/,相关的更多介绍可以参考官方文档网址:
    https://calcite.apache.org/docs/
  • 第二步:根据查询到的元数据对SQL语句中的语法进行校验,通过第一步中获取到的SqlNode节点树中的信息来获取SQL语句中包含的表、字段、函数等信息,然后通过和元数据进行比对来判断SQL语句中包含的表、字段等信息在元数据中是否存在。
  • 第三步:通过结合元数据信息对SqlNode节点树的进一步解析得到关系表达式树,生成初步的逻辑执行计划。
  • 第四步:对第三步生成的逻辑执行计划进行进一步优化得到最优的逻辑执行计划,这一步得到结果还是关系表达式树。
  • 第五步:将逻辑执行计划转变为物理执行计划,提交给Flink 集群进行执行。《数据资产管理核心技术与应用》读书笔记

具体的代码实现,由于代码较多,请参考纸质书。

1.5、   从数据任务的编排系统中获取数据血缘

数据任务的编排系统通常是对不同的数据节点类型的任务进行前后运行顺序以及依赖关系的编排,如下图所示。

具体的代码实现,由于代码较多,请参考纸质书。

2、数据血缘的存储模型与展示设计

从架构设计的角度来看,血缘数据存储需要注意如下几点:《数据资产管理核心技术与应用》读书笔记

  • 可扩展性:支持对数据血缘的源端进行扩展,比如当前只需要支持 Hive、Spark执行计划、Spark SQL等,但是未来可能会新增其他数据血缘来源。如果出现新的数据血缘来源时,要做到对现有的设计不做改动便可支持。
  • 可跟踪性:需要记录数据血缘的变更记录,方便将来做追踪,比如数据血缘出现变更时,需要将其变更的过程记录下来,而不是在数据血缘发生变化后,直接替换现有的已经采集入库的数据血缘关系。
  • 可维护性:支持手动维护,比如支持人工维护数据血缘或者数据血缘采集错误时,支持人工修改。

数据血缘的采集和处理的过程通常如下图所示,实时获取原始数据,然后发送到类似Kafka这样的消息队列中,然后对原始数据进行解析,生成血缘数据,然后入库保存。

在血缘数据解析入库后,就可以对数据血缘做展示了,关于数据血缘的展示设计参考如下图所示,一般需要注意如下几点:

  • 支持表级血缘,默认展示表级血缘关系,选择单个表时,还可以点击查看该表的上游血缘或者下游血缘。
  • 详情中支持字段级血缘展示,点击图中表的字段详情时,可以继续展开显示字段级的血缘关系。
  • 血缘关系中,支持点击查看血缘的解析来源,比如SparkSQL语句、Spark执行计划等。

从下图可以看到表与表之间以及字段与字段之间的血缘关系展示。当某一张表发生变更时,很容易的就知道对下游或者上游的哪些表和字段产生影响,从而可以加快很多问题的处理和定位。在使用某张表的数据时,也能追溯到该表的原始数据表以及经过了哪些中间表的处理,数据的链路变得非常清晰,对数据的使用者来说,产生了极大的帮助。《数据资产管理核心技术与应用》读书笔记

在学习和开发Python的时候,第一步的工作就是先准备好开发环境,包括相关常用的插件,以及一些辅助工具,这样我们在后续的开发工作中,才能做到事半功倍。下面介绍一些Python 开发环境的准备以及一些常用类库模块的安装和使用的经验总结,供大家参考了解。

1、开发VScode的安装及相关准备

在 Python 开发环境的准备中,有几个步骤是关键的。以下是一个详细的指南,涵盖了开发环境的准备以及一些常用插件的安装:

1)安装 VS Code
VS Code:
这是一个轻量级但功能强大的代码编辑器,支持丰富的扩展。你可以从
Visual Studio Code 官方网站
下载。打开官网 https://code.visualstudio.com/,下载软件包。或者你也可以使用其他的如
PyCharm,
可以从
JetBrains 官方网站
下载。

Python AI 编程助手:Fitten Code:

它是由非十大模型驱动的 AI 编程助手,它可以自动生成代码,提升开发效率,帮您调试 Bug,节省您的时间,另外还可以对话聊天,解决您编程碰到的问题。

Fitten Code是由非十大模型驱动的AI编程助手,它可以自动生成代码,提升开发效率,帮您调试Bug,节省您的时间。还可以对话聊天,解决您编程碰到的问题。免费且支持80多种语言:Python、C++、Javascript、Typescript、Java等。

强烈推荐使用
,自动补齐代码功能,可以节省很多手工键入代码的时间,减少错误。

2)安装 VS Code Python 扩展
在VSCode中安装 Python 扩展,在扩展市场搜索 Python 并安装。

3)安装 Python
首先,确保你已经安装了 Python。你可以从
Python 官方网站
下载最新版本安装包并安装。
Window 平台安装 Python: https://www.python.org/downloads/windows/
Mac 平台安装 Python: https://www.python.org/downloads/mac-osx/

4)配置 Python 环境变量
打开系统环境变量,在 PATH 变量中添加 Python 目录,这样可以在命令行中直接使用 Python。

5)测试 Python 环境
在命令行中输入 python,如果出现 Python 解释器版本信息,则表示 Python 环境配置成功。

6)安装 pip
打开命令行,输入 pip install --upgrade pip,升级 pip 到最新版本。

7)安装 virtualenv
打开命令行,输入 pip install virtualenv,安装 virtualenv。

2、Python一些常用类库模块的安装

Python开发常用类库模块非常多,看你侧重于那个方面,基本上都时列出来一大串,我以常规后端Web API开发为侧重点进行一些重点的推介,供参考学习。

1) requests

requests
是一个简单易用的 Python 库,地址:https://github.com/psf/requests,用于发送 HTTP 请求。它的设计目标是使得与 Web 服务的交互更加方便和人性化。
requests
是基于 urllib3 之上的一个封装层,提供了简洁的 API 来处理常见的 HTTP 请求操作,如 GET、POST、PUT、DELETE 等。

requests
的主要特性

  • 简洁的 API
    :相比原生的
    urllib

    requests
    提供了更直观、更容易理解的接口。
  • 自动处理编码

    requests
    自动处理响应的内容编码,并自动解码
    gzip

    deflate
    压缩。
  • 支持保持会话
    :通过
    Session
    对象,
    requests
    可以在多个请求之间保持会话,处理 cookies。
  • 简化的错误处理

    requests
    会根据 HTTP 响应状态码抛出相应的异常,从而简化错误处理流程。
  • 丰富的功能
    :支持 HTTP 认证、代理、SSL 证书验证、文件上传、多部分编码表单、会话对象、cookie 持久化、连接池管理等功能。

如果需要考虑异步处理,可以使用
aiohttp :
aiohttp
是一个异步 HTTP 客户端和服务器框架,它使用 Python 的
asyncio
库来处理大量并发的请求。
aiohttp
适合那些需要高性能网络通信的应用,如 Web 服务、WebSocket 和实时数据处理。

2) Uvicorn

Uvicorn
是一个基于 ASGI(Asynchronous Server Gateway Interface)的高性能、轻量级的 Python Web 服务器,专为运行异步 Web 框架(如 FastAPI、Starlette)而设计。它利用了 Python 的异步功能,能够处理大量并发连接,适合构建现代的异步 Web 应用程序。

Uvicorn
的主要特性

  • 高性能
    : 使用
    uvloop

    httptools
    提供极高的性能,适合在高并发场景下使用。
  • 异步支持
    : 支持异步编程模型,能够与 Python 的
    asyncio

    trio
    无缝集成。
  • ASGI 兼容
    : 完全兼容 ASGI 标准,适用于现代异步 Web 框架,如 FastAPI 和 Starlette。
  • WebSocket 支持
    : 通过 ASGI,
    Uvicorn
    原生支持 WebSocket 协议。
  • 灵活的部署
    : 既可以作为独立的开发服务器使用,也可以与
    Gunicorn
    等 WSGI 服务器结合部署生产环境。
安装 Uvicorn
pip install uvicorn


运行 Uvicorn
uvicorn testuvicorn:app --reload

Uvicorn
通常用于运行 FastAPI 或 Starlette 应用。以下是一个简单的 FastAPI 应用并使用
Uvicorn
运行:

from fastapi importFastAPI

app
=FastAPI()

@app.get(
"/")
async
defread_root():return {"Hello": "World"}if __name__ == "__main__":importuvicorn
uvicorn.run(app, host
="0.0.0.0", port=8000)
Uvicorn 提供了丰富的配置选项,以满足不同需求。可以通过命令行参数或配置文件来配置 Uvicorn 的行为。
以下是一些常用的配置选项:
--host:指定主机地址,默认为 127.0.0.1。
--port:指定端口号,默认为 8000。
--workers:指定工作进程数量,默认为 CPU 核心数的 1 倍。
--log-level:指定日志级别,默认为 info。
--reload:在代码修改时自动重新加载应用程序。

3)FastAPI

FastAPI
是一个现代、快速(高性能)的 Web 框架,用于构建 API。它基于 Python 3.7+ 的类型提示,并且依赖于
Starlette
(用于 web 服务器和路由)和
Pydantic
(用于数据验证和序列化)。
FastAPI
的设计目标是提供与 Flask 和 Django 类似的开发体验,但在性能、类型安全和开发者友好性方面做出更大的提升。GitHub地址:https://github.com/fastapi/fastapi

FastAPI 的主要特性

  • 极高的性能
    : 基于 ASGI 的异步支持,使得
    FastAPI
    在性能上接近 Node.js 和 Go 的水平,适合处理高并发。
  • 自动生成 API 文档
    : 使用 OpenAPI 和 JSON Schema 自动生成交互式的 API 文档(如 Swagger UI 和 ReDoc)。
  • 基于类型提示的自动验证
    : 利用 Python 的类型提示和
    Pydantic
    ,自动进行数据验证和解析。
  • 异步支持
    : 原生支持
    async

    await
    ,能够处理异步任务,适合与数据库、第三方 API、WebSocket 等交互。
  • 内置依赖注入系统
    : 使得依赖的声明和管理变得简洁而强大,便于模块化设计。
  • 开发者友好
    : 提供了详细的错误信息和文档,支持自动补全,极大提升了开发效率。

以下是一个简单的
FastAPI
应用:

from fastapi importFastAPI

app
=FastAPI()

@app.get(
"/")
async
defread_root():return {"message": "Hello, World"}

@app.get(
"/items/{item_id}")
async
def read_item(item_id: int, q: str =None):return {"item_id": item_id, "q": q}

当你运行 FastAPI 应用时,它会自动生成交互式文档:

  • Swagger UI
    : 访问
    http://127.0.0.1:8000/docs
  • ReDoc
    : 访问
    http://127.0.0.1:8000/redoc

这两个文档界面可以让你查看 API 的结构,甚至可以直接在界面中进行 API 调用。如我在上篇随笔进行介绍的《
Python中FastAPI项目使用 Annotated的参数设计
》。

FastAPI 是一个非常现代化和高效的框架,非常适合用于构建高性能的 API。其自动文档生成、数据验证和依赖注入等特性,使得开发者能够更快、更安全地编写代码,并提供出色的用户体验。

FastAPI项目的参数设计,这些您可以在
路径操作函数
参数或使用
Annotated
的依赖函数中使用的特殊函数,用于从请求中获取数据。

我们引入配置文件,可以对FastAPI 中服务启动的参数进行统一的管理,如下main.py 代码所示。

if __name__ == "__main__":importuvicorn#log_level:'critical', 'error', 'warning', 'info', 'debug', 'trace'。默认值:'info'。
uvicorn.run(
app,
host
=settings.SERVER_IP,
port
=settings.SERVER_PORT,
log_config
="app/uvicorn_config.json", #日志配置 #log_level="info", # 日志级别 )

3)pymysql 、pymssql、和 SQLAlchemy

涉及后端的处理,肯定绕不过数据库的处理操作,如对于MySQL、MS SqlServer等数据库的处理和封装。

PyMySQL
是一个纯 Python 实现的 MySQL 客户端库,用于连接 MySQL 数据库并执行 SQL 查询。它是 Python 的
MySQLdb
库的替代品,尤其适合那些在使用 Python 3 并且不希望依赖 C 语言扩展的项目。
PyMySQL
支持 MySQL 数据库的所有主要功能,包括事务、存储过程、连接池等。

PyMySQL
的主要特性

  • 纯 Python 实现
    : 不依赖 C 扩展,易于安装和跨平台使用。
  • 兼容性好
    : 与
    MySQLdb
    的接口非常相似,便于从
    MySQLdb
    迁移到
    PyMySQL
  • 支持 MySQL 的所有主要功能
    : 包括事务处理、存储过程、BLOB 数据类型等。
  • 简单易用
    : 提供了直观的 API 进行数据库连接、查询、插入、更新和删除操作。

安装
PyMySQL

你可以通过
pip
来安装
PyMySQL
:

pip install pymysql

使用
PyMySQL
连接到 MySQL 数据库:

importpymysql

connection
=pymysql.connect(
host
='localhost',
user
='your_username',
password
='your_password',
database
='your_database')try:
with connection.cursor() as cursor:
#执行 SQL 查询 cursor.execute("SELECT VERSION()")#获取查询结果 result =cursor.fetchone()print(f"MySQL version: {result}")finally:
connection.close()

如下是我实际表的一些操作例子代码。

sql = "select * from t_customer where name = '{0}' LIMIT 1".format(name)print(sql)
cursor.execute(sql)
myresult
= cursor.fetchone() #fetchone() 获取一条记录 ifmyresult:print("该名称已存在,请更换名称.")else:print("该名称可用.")#插入记录语句 sql = "INSERT INTO `t_customer` (`ID`, `Name`, `Age`, `Creator`, `CreateTime`) VALUES (%s, %s, %s, %s, %s);"val=(id, name, age, creator, createtime)

cursor.execute(sql, val)
db.commit()
#数据表内容有更新,必须使用到该语句 print(cursor.rowcount, "行记录插入.")

sql
= "update t_customer Set age = %s where name =%s"val= (26, name)
cursor.execute(sql, val)
db.commit()
#数据表内容有更新,必须使用到该语句 print(cursor.rowcount, "条记录被修改")

sql
= "select * from t_customer where name = '{0}' LIMIT 1".format(name)
cursor.execute(sql)
myresult
= cursor.fetchone() #fetchone() 获取一条记录 ifmyresult:print("修改后的记录:", myresult)

sql
= "SELECT * FROM t_customer"cursor.execute(sql)print("t_customer 结果集:")for x incursor:print(x)

sql
= "delete from t_customer where name =%s" try:
cursor.execute(sql, (name,))
db.commit()
#数据表内容有更新,必须使用到该语句 print(cursor.rowcount, "行记录删除.")except:
db.rollback()
#发生错误时回滚 print("删除记录失败!")


sql
= "SELECT * FROM t_customer"cursor.execute(sql)
myresult
= cursor.fetchall() #fetchall() 获取所有记录 for x inmyresult:print(x)#关闭数据库连接 db.close()

输出的显示如下所示。

pymssql
是一个用于连接 Microsoft SQL Server 数据库的 Python 库,它是基于
FreeTDS
实现的轻量级数据库接口,旨在简化 Python 与 SQL Server 之间的交互。
pymssql
提供了对 T-SQL 语句的支持,并且可以执行存储过程和处理大批量数据插入等任务。

pymssql
的主要特性

  • 轻量级和易用性
    : 提供了简单的 API 接口,易于快速上手。
  • 与 SQL Server 兼容
    : 支持 Microsoft SQL Server 2005 及以上版本。
  • 跨平台支持
    : 支持在 Windows、Linux 和 macOS 系统上运行。
  • 集成事务管理
    : 通过
    commit

    rollback
    方法进行事务管理。
  • 支持存储过程
    : 能够执行和处理存储过程,适用于复杂的数据库操作。
  • 批量插入支持
    : 通过
    executemany
    方法高效地插入大量数据。

安装
pymssql

你可以通过
pip
安装
pymssql
:

pip install pymssql

使用
pymssql
连接到 SQL Server 数据库,
pymssql
支持事务,可以在执行多个操作时使用事务控制,以确保数据一致性:

importpymssql#Connect to the database
conn =pymssql.connect(
server
="localhost",
user
="sa",
password
="123456",
database
="Winframework",
tds_version
="7.0",
)
#Create a cursor object cursor =conn.cursor()#Execute a query cursor.execute("SELECT * FROM T_Customer")#Fetch all the rows rows =cursor.fetchall()#Print the rows for row inrows:print(row)#Close the cursor and connection cursor.close()
conn.close()

SQLAlchemy
是一个功能强大且灵活的 Python SQL 工具包和对象关系映射(ORM)库。它被广泛用于在 Python 项目中处理关系型数据库的场景,既提供了高级的 ORM 功能,又保留了对底层 SQL 语句的强大控制力。
SQLAlchemy
允许开发者通过 Python 代码与数据库进行交互,而无需直接编写 SQL 语句,同时也支持直接使用原生 SQL 进行复杂查询。
Engine  连接         驱动引擎
Session 连接池,事务  由此开始查询
Model   表              类定义
Column  列
Query   若干行         可以链式添加多个条件

SQLAlchemy 的主要特性

  • 对象关系映射(ORM)
    : 允许将 Python 类映射到数据库表,并且自动处理 SQL 的生成和执行。
  • SQL 表达式语言
    : 提供了一个表达式语言层,允许构建和执行原生 SQL 查询,同时保留类型安全性和跨数据库兼容性。
  • 数据库抽象层
    : 提供了跨数据库的兼容性,使得在不同数据库之间切换变得相对容易。
  • 高性能
    : 通过细粒度的控制和缓存机制,优化了数据库访问的性能。
  • 事务管理
    : 支持复杂的事务处理和上下文管理,使得数据库操作更加安全和一致。
  • 支持多种数据库
    : 支持大多数主流的关系型数据库,如 SQLite、PostgreSQL、MySQL、Oracle、SQL Server 等。

安装 SQLAlchemy

你可以通过
pip
安装
SQLAlchemy

pip install sqlalchemy

如果你要连接到特定的数据库,还需要安装相应的数据库驱动程序。例如,要连接到 MySQL 数据库,你还需要安装
pymysql

mysqlclient

使用
SQLAlchemy 操作数据库,
可以统一多种数据库的操作处理,如SQLITE、SqlServer、MySQL、PostgreSQL等。

使用
SQLAlchemy
创建与数据库的连接:

#mysql 数据库引擎
engine =create_engine("mysql+pymysql://root:123456@127.0.0.1:3306/WinFramework",
pool_recycle
=3600,#echo=True, )#Sqlite 数据库引擎#engine = create_engine("sqlite:///testdir//test.db") #PostgreSQL 数据库引擎#engine = create_engine(#"postgresql+psycopg2://postgres:123456@localhost:5432/winframework",## echo=True,#) #engine = create_engine(#"mssql+pymssql://sa:123456@localhost/WinFramework?tds_version=7.0",## echo=True,#)

由于对应的是ORM处理方式,因此和数据库表关联需要定义一个类对象,如下所示。

from sqlalchemy importcreate_engine, Column, Integer, String, DateTime, TIMESTAMPfrom sqlalchemy.ext.declarative importdeclarative_basefrom sqlalchemy.orm importsessionmaker#创建一个基类,用于定义数据库表的结构
Base =declarative_base()#定义一个 Customer数据库表的模型
classCustomer(Base):__tablename__ = "t_customer"id= Column(String, primary_key=True, comment="主键")
name
= Column(String, comment="姓名")
age
= Column(Integer, comment="年龄")
creator
= Column(String, comment="创建人")
createtime
= Column(DateTime, comment="创建时间")

CRUD的操作例子代码如下所示。

#创建一个会话
Session = sessionmaker(bind=engine)
session
=Session()

id
=str(guid.uuid4())#create a new customer customer =Customer(
id
=id,
name
="Alice",
age
=25,
creator
="admin",
createtime
=datetime.strptime("2021-01-01 12:00:00", "%Y-%m-%d %H:%M:%S"),
)
#add the customer to the session session.add(customer)#commit the changes to the database session.commit()#query the customer from the session for item insession.scalars(select(Customer)):print(item.id, item.name, item.age, item.creator, item.createtime)print("\r\nquery all customers")
customers
=session.query(Customer).all()for customer incustomers:print(customer.name, customer.age)print("\r\nquery all customers by condition:age > 20")
customers
= session.query(Customer).filter(Customer.age > 20).limit(30).offset(1).all()for customer incustomers:print(customer.name, customer.age)print("\r\nquery customer by id")
customer
= session.query(Customer).filter(Customer.id ==id).first()ifcustomer:print(customer.name, customer.age)print("\r\n 复杂查询")
customers
=(
session.query(Customer)
.filter(
or_(
and_(Customer.age
> 20, Customer.age < 30),
Customer.name.in_([
"Alice", "伍华聪"]),
)
)
.all()
)
for customer incustomers:print(customer.name, customer.age)print("\r\nselect customer by id")
stmt
= select(Customer).where(Customer.id ==id)
result
=session.execute(stmt)print(result)


stmt
= select(Customer).where(Customer.name == "伍华聪")
result
=session.execute(stmt).scalar()ifresult:print("Customer exists in the database")print(result.id, result.name, result.age)else:print("Customer does not exist in the database")print("\r\nselect customer In")#query the customer from the session stmt = select(Customer).where(Customer.name.in_(["Alice", "伍华聪"]))for item insession.scalars(stmt):print(item.id, item.name, item.age, item.creator, item.createtime)print('\r\ndelete all customers by name = "Alice"')#delete the customer from the database delete_stmt = delete(Customer).where(Customer.name == "Alice")
result
=session.execute(delete_stmt)print(str(result.rowcount) + "rows deleted")

session.commit()
#close the session session.close()

由于篇幅限制,我们暂时介绍一些,其实就算是做后端WebAPI的处理,我们也需要了解很多不同的类库,Python类库非常丰富,而且同步、异步又有不同的类库差异,因此我们可以根据实际需要选用不同的类库来实现我们的框架目的。

如对于FastAPI的数据验证,我们一般引入 pydantic,可以对数据进行各种丰富的校验处理,类似于强类型和各种规则的校验。

classPerson(BaseModel):
name: str
age: int

@field_validator(
"age")defage_must_be_positive(cls, v):if v <0:raise ValueError("Age must be a positive number")return v

如对于配置信息的处理,我们还可以引入 python-dotenv 和  pydantic_settings 来统一管理配置参数。

from pydantic_settings importBaseSettings, SettingsConfigDictclassSettings(BaseSettings):
model_config
=SettingsConfigDict(
env_file
=".env", #加载env文件 extra="ignore", #加载env文件,如果没有在Settings中定义属性,也不抛出异常 env_file_encoding="utf-8",
env_prefix
="",
case_sensitive
=False,
)
#Env Server SERVER_IP: str = "127.0.0.1"SERVER_PORT: int= 9000 #Env Database DB_NAME: str = "winframework"DB_USER: str= "root"DB_PASSWORD: str= "123456"DB_HOST: str= "localhost"DB_PORT: int= 3306DB_URI: str=(
f
"mysql+pymysql://{DB_USER}:{DB_PASSWORD}@{DB_HOST}:{DB_PORT}/{DB_NAME}")
.............
settings = Settings()

还有对于一些常规的文件格式,如json格式,txt格式的文件处理,以及PDF文件、Excel文件、图片操作、声音处理、二维码处理等,都有不同的类库提供辅助处理,我们可以从中择优选择即可。

Python的世界丰富多彩,让我们一起探索并应用在实践当中。

Excel 是一款广泛应用于数据处理、分析和报告制作的电子表格软件。在商业、学术和日常生活中,Excel 的使用极为普遍。本文将详细介绍如何使用免费.NET库将数据写入到 Excel 中,包括文本、数值、数组、和DataTable数据的输入。

  • C# 在Excel单元格中写入文本、或数值
  • C# 在Excel工作表中写入数组
  • C# 在Excel工作表中写入DataTable数据表

本文用到的免费.NET Excel库为
Free Spire.XLS for .NET

该库可以在Visual Studio > NuGet程序包管理器中搜索 “
FreeSpire.XLS
” 来安装。也可以通过
此链接
下载产品包后手动添加引用。

C# 在Excel单元格中写入文本、或数值

1. 创建一个工作簿
Workbook
对象;

2. 获取指定工作表;

3. 写入数据到指定单元格:

写入文本

Worksheet.Range[].Text

Worksheet.Range[].Value
属性;

写入数字

Worksheet.Range[].Value2
属性;

4. 保存Excel文件。

C#代码:

usingSpire.Xls;namespaceWriteDataToCells
{
classProgram
{
static void Main(string[] args)
{
//创建一个Excel工作簿 Workbook workbook = newWorkbook();//获取其中第一张工作表 Worksheet worksheet = workbook.Worksheets[0];//写入数据到指定单元格 worksheet.Range["A1"].Text = "考号";
worksheet.Range[
"B1"].Text = "学生姓名";
worksheet.Range[
"C1"].Value = "所在班级";
worksheet.Range[
"D1"].Value = "考试成绩";

worksheet.Range[
"A2"].Value = "TS001";
worksheet.Range[
"B2"].Value = "陈国柏";
worksheet.Range[
"C2"].Value = "5班";
worksheet.Range[
"D2"].Value2 = 97;

worksheet.Range[
"A3"].Value = "TS002";
worksheet.Range[
"B3"].Value = "易江维";
worksheet.Range[
"C3"].Value = "2班";
worksheet.Range[
"D3"].Value2 = 92;//设置字体样式 worksheet.Range["A1:D1"].Style.Font.IsBold = true;
worksheet.Range[
"A1:D3"].Style.Font.Size = 11;
worksheet.Range[
"A1:D3"].Style.Font.FontName = "宋体";//保存Excel文件 workbook.SaveToFile("写入数据到单元格.xlsx", ExcelVersion.Version2016);
}
}
}

C# 在Excel工作表中写入数组

1. 创建一个工作簿
Workbook
对象;
2. 获取指定工作表;
3. 定义一个二维数组;
4. 通过
Worksheet.InsertArray(Object\[,\] objectArray, int firstRow, int firstColumn)
方法将二维数组中的数据插入到工作表中指定位置;
5. 保存Excel文件。

C#代码:

usingSpire.Xls;namespaceWriteArraysToWorksheet
{
classProgram
{
static void Main(string[] args)
{
//创建一个Excel工作簿 Workbook workbook = newWorkbook();//获取其中第一张工作表 Worksheet worksheet = workbook.Worksheets[0];//创建一个二维数组 string[,] twoDimensionalArray = new string[,]{

{
"统计年份", "城市", "销售额", "增长率"},
{
"2021", "上海", "150万", "55%"},
{
"2021", "杭州", "80万", "-12%"},
{
"2021", "北京", "100万", "20%"}
};
//将数组写入工作表指定位置 worksheet.InsertArray(twoDimensionalArray, 1, 1);//设置字体样式 worksheet.Range["A1:D1"].Style.Font.IsBold = true;
worksheet.Range[
"A1:D4"].Style.Font.Size = 11;
worksheet.Range[
"A1:D4"].Style.Font.FontName = "宋体";//保存Excel文件 workbook.SaveToFile("写入数组.xlsx", ExcelVersion.Version2016);
}
}
}

C# 在Excel工作表中写入DataTable数据表

1. 创建一个工作簿
Workbook
对象;
2. 获取指定工作表;
3. 创建一个
DataTable
对象,并添加数据;
4. 使用
Worksheet.InsertDataTable(DataTable dataTable,bool columnHeaders, int firstRow, int firstColumn, bool transTypes)
方法将DataTable的内容插入到工作表中指定位置;
5. 保存Excel文件。
C#代码:

usingSystem;usingSystem.Data;usingSystem.Drawing;usingSpire.Xls;namespaceWriteDataTableToWorksheet
{
classProgram
{
static void Main(string[] args)
{
//创建一个Excel工作簿 Workbook workbook = newWorkbook();//获取其中第一张工作表 Worksheet worksheet = workbook.Worksheets[0];//创建DataTable对象 DataTable dataTable = newDataTable();
dataTable.Columns.Add(
"编码", typeof(Int32));
dataTable.Columns.Add(
"产品", typeof(String));
dataTable.Columns.Add(
"单价", typeof(Decimal));//创建行并添加数据 DataRow dr =dataTable.NewRow();
dr[
0] = 110600015;
dr[
1] = "数据线";
dr[
2] = "8.5";
dataTable.Rows.Add(dr);

dr
=dataTable.NewRow();
dr[
0] = 110600037;
dr[
1] = "鼠标";
dr[
2] = "29.9";
dataTable.Rows.Add(dr);

dr
=dataTable.NewRow();
dr[
0] = 110600021;
dr[
1] = "网线";
dr[
2] = "15.5";
dataTable.Rows.Add(dr);
//将datatable中的数据写入工作表 worksheet.InsertDataTable(dataTable, true, 1, 1, true);//设置字体样式 worksheet.Range["A1:D1"].Style.Font.IsBold = true;
worksheet.Range[
"A1:D4"].Style.Font.Size = 11;
worksheet.Range[
"A1:D4"].Style.Font.FontName = "宋体";//保存Excel文件 workbook.SaveToFile("写入DataTable.xlsx", ExcelVersion.Version2016);
}
}
}

通过以上提供的三个示例,你可以将各种类型的数据写入到 Excel工作表中。如需对Excel中的数据进行进一步的分析处理、或插入图表等元素,可以点击查看该免费Spire.XLS库提供相应功能教程:
https://www.e-iceblue.cn/spirexls/spire-xls-for-net-program-guide-content.html

1.scrapy-redis的环境准备

pip install scrapy-redis

安装完毕之后确保其可以正常导入使用即可。

2. 实现

接下来我们只需要简单的几步操作就可以实现分布式爬虫的配置了。

2.1修改 Scheduler

在前面的课时中我们讲解了 Scheduler 的概念,它是用来处理 Request、Item 等对象的调度逻辑的,默认情况下,Request 的队列是在/
内存/
中的,为了实现分布式,我们需要将队列迁移到 Redis 中,这时候我们就需要修改 Scheduler,修改非常简单,只需要在 settings.py 里面添加如下代码即可:

SCHEDULER = "scrapy_redis.scheduler.Scheduler"

这里我们将 Scheduler 的类修改为 Scrapy-Redis 提供的 Scheduler 类,这样在我们运行爬虫时,Request 队列就会出现在 Redis 中了。

2.2修改 Redis 连接信息

另外我们还需要修改下 Redis 的连接信息,这样 Scrapy 才能成功连接到 Redis 数据库,修改格式如下:

REDIS_URL = 'redis://[user:pass]@hostname:9001'

在这里我们需要根据如上的格式来修改,由于我的 Redis 是在本地运行的,所以在这里就不需要填写用户名密码了,直接设置为如下内容即可:

REDIS_URL = 'redis://localhost:6379'

2.3修改去重类

既然 Request 队列迁移到了 Redis,那么相应的去重操作我们也需要迁移到 Redis 里面,前一节课我们讲解了 Dupefilter 的原理,这里我们就修改下去重类来实现基于 Redis 的去重:

DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"

2.4配置持久化

一般来说开启了 Redis 分布式队列之后,我们不希望爬虫在关闭时将整个队列和去重信息全部删除,因为很有可能在某个情况下我们会手动关闭爬虫或者爬虫遭遇意外终止,为了解决这个问题,我们可以配置 Redis 队列的持久化,修改如下:

SCHEDULER_PERSIST = True

好了,到此为止我们就完成分布式爬虫的配置了。

3.运行

上面我们完成的实际上并不是真正意义的分布式爬虫,因为 Redis 队列我们使用的是本地的 Redis,所以多个爬虫需要运行在本地才可以,如果想实现真正意义的分布式爬虫,可以使用远程 Redis,这样我们就能在多台主机运行爬虫连接此 Redis 从而实现真正意义上的分布式爬虫了。

更多精致内容

无缝融入,即刻智能[一]:Dify-LLM大模型平台,零编码集成嵌入第三方系统,42K+星标见证专属智能方案

1.Dify 简介

1.1 功能情况

Dify,一款引领未来的开源大语言模型(LLM)应用开发平台,革新性地融合了后端即服务(Backend as a Service,BaaS)与LLMOps的精髓,为开发者铺设了一条从创意原型到高效生产的快车道。其设计旨在打破技术壁垒,让非技术背景的用户也能轻松参与至AI应用的构思与数据运营之中,共同塑造智能未来。

Dify内嵌了构建LLM应用的全方位技术基石,覆盖了从模型库的海量选择(支持数百种模型)到高效直观的Prompt编排界面,再到卓越品质的检索增强生成(RAG)引擎与稳固可靠的Agent框架。这一集成的技术栈,不仅极大地简化了开发流程,还赋予了开发者前所未有的灵活性与创意空间。通过其灵活的流程编排功能及用户友好的界面与API接口,Dify帮助开发者有效规避了重复劳动,使他们能够将宝贵的时间和精力集中于创新思考与业务需求的深度挖掘上。

Dify 一词源自 Define + Modify,意指定义并且持续的改进你的 AI 应用,它是为你而做的(Do it for you)。

  • 核心功能列表:


    1. 工作流
      : 在画布上构建和测试功能强大的 AI 工作流程,利用以下所有功能以及更多功能。


    1. 全面的模型支持
      : 与数百种专有/开源 LLMs 以及数十种推理提供商和自托管解决方案无缝集成,涵盖 GPT、Mistral、Llama3 以及任何与 OpenAI API 兼容的模型。


    1. Prompt IDE
      : 用于制作提示、比较模型性能以及向基于聊天的应用程序添加其他功能(如文本转语音)的直观界面。

    2. RAG Pipeline
      : 广泛的 RAG 功能,涵盖从文档摄入到检索的所有内容,支持从 PDF、PPT 和其他常见文档格式中提取文本的开箱即用的支持。



    1. Agent 智能体
      : 您可以基于 LLM 函数调用或 ReAct 定义 Agent,并为 Agent 添加预构建或自定义工具。Dify 为 AI Agent 提供了50多种内置工具,如谷歌搜索、DALL·E、Stable Diffusion 和 WolframAlpha 等。

    2. LLMOps
      : 随时间监视和分析应用程序日志和性能。您可以根据生产数据和标注持续改进提示、数据集和模型。



    1. 后端即服务
      : 所有 Dify 的功能都带有相应的 API,因此您可以轻松地将 Dify 集成到自己的业务逻辑中。
  • 功能对比

  • 框架原理图

1.2 关键技术特性

  • 本地模型推理 Runtime 支持
    :Xinference(推荐),OpenLLM,LocalAI,ChatGLM,Ollama,NVIDIA TIS

  • Agentic Workflow 特性
    :支持节点


    • LLM
    • 知识库检索
    • 问题分类
    • 条件分支
    • 代码执行
    • 模板转换
    • HTTP 请求
    • 工具
  • RAG特性:


    • 索引方式
      • 关键词
      • 文本向量
      • 由 LLM 辅助的问题-分段模式
    • 检索方式
      • 关键词
      • 文本相似度匹配
      • 混合检索
      • 多路召回
    • 召回优化技术
      • 使用 ReRank 模型
  • 向量数据库支持:Qdrant,Weaviate,Zilliz/Milvus,Pgvector,Pgvector-rs,Chroma,OpenSearch,TiDB,Tencent Vector,Oracle

1.3 云服务

Dify 为所有人提供了云服务,你无需自己部署即可使用 Dify 的完整功能。要使用 Dify 云服务,你需要有一个 GitHub 或 Google 账号。

  • 登录
    Dify 云服务
    ,创建一个或加入已有的 Workspace

  • 配置你的模型供应商,或使用我们提供的托管模型供应商

  • 可以创建应用了

1.4 更多LLM平台参考:

2. 社区版部署

2.1 Docker Compose 部署(推荐)

git clone https://github.com/langgenius/dify.git
  • 启动 Dify
#进入 Dify 源代码的 docker 目录,执行一键启动命令:
cd dify/docker
cp .env.example .env
docker compose up -d

如果您的系统安装了 Docker Compose V2 而不是 V1,请使用 docker compose 而不是 docker-compose。通过$ docker compose version检查这是否为情况。在这里阅读更多信息。

遇到pulling失败问题,请添加镜像源,参考上述推荐文章有解决方案

  • 部署结果展示:

最后检查是否所有容器都正常运行:

docker compose ps

包括 3 个业务服务 api / worker / web,以及 6 个基础组件 weaviate / db / redis / nginx / ssrf_proxy / sandbox 。

NAME                  IMAGE                              COMMAND                  SERVICE      CREATED          STATUS                    PORTS
docker-api-1          langgenius/dify-api:0.6.16         "/bin/bash /entrypoi…"   api          15 minutes ago   Up 15 minutes             5001/tcp
docker-db-1           postgres:15-alpine                 "docker-entrypoint.s…"   db           15 minutes ago   Up 15 minutes (healthy)   5432/tcp
docker-nginx-1        nginx:latest                       "sh -c 'cp /docker-e…"   nginx        15 minutes ago   Up 15 minutes             0.0.0.0:80->80/tcp, :::80->80/tcp, 0.0.0.0:443->443/tcp, :::443->443/tcp
docker-redis-1        redis:6-alpine                     "docker-entrypoint.s…"   redis        15 minutes ago   Up 15 minutes (healthy)   6379/tcp
docker-sandbox-1      langgenius/dify-sandbox:0.2.1      "/main"                  sandbox      15 minutes ago   Up 15 minutes             
docker-ssrf_proxy-1   ubuntu/squid:latest                "sh -c 'cp /docker-e…"   ssrf_proxy   15 minutes ago   Up 15 minutes             3128/tcp
docker-weaviate-1     semitechnologies/weaviate:1.19.0   "/bin/weaviate --hos…"   weaviate     15 minutes ago   Up 15 minutes             
docker-web-1          langgenius/dify-web:0.6.16         "/bin/sh ./entrypoin…"   web          15 minutes ago   Up 15 minutes             3000/tcp
docker-worker-1       langgenius/dify-api:0.6.16         "/bin/bash /entrypoi…"   worker       15 minutes ago   Up 15 minutes             5001/tcp
  • 更新 Dify

进入 dify 源代码的 docker 目录,按顺序执行以下命令:

cd dify/docker
docker compose down
git pull origin main
docker compose pull
docker compose up -d

同步环境变量配置 (重要!)

  • 如果 .env.example 文件有更新,请务必同步修改您本地的 .env 文件。

  • 检查 .env 文件中的所有配置项,确保它们与您的实际运行环境相匹配。您可能需要将 .env.example 中的新变量添加到 .env 文件中,并更新已更改的任何值。

  • 访问 Dify

docker 部署运行完成后,输入指令sudo docker ps即可看到运行的容器,其中在运行的容器列表可以看到有个 nginx 的容器,且对外访问的是 80 端口,这个就是外部访问的端口,下面我们进行本地访问测试

在浏览器中输入
http://localhost
访问 Dify。访问
http://127.0.0.1:80
即可使用本地部署的 Dify。

10.80.2.195:80

随便填写,进入界面

  • 自定义配置

编辑 .env 文件中的环境变量值。然后,重新启动 Dify:

docker compose down
docker compose up -d

完整的环境变量集合可以在 docker/.env.example 中找到。

2.2 本地码源部署

  • 前置条件

Clone Dify 代码:

git clone https://github.com/langgenius/dify.git

在启用业务服务之前,需要先部署 PostgresSQL / Redis / Weaviate(如果本地没有的话),可以通过以下命令启动:

cd docker
cp middleware.env.example middleware.env
docker compose -f docker-compose.middleware.yaml up -d
  1. 进入 api 目录
cd api
  1. 复制环境变量配置文件.
cp .env.example .env
  1. 生成随机密钥,并替换 .env 中 SECRET_KEY 的值
openssl rand -base64 42
sed -i 's/SECRET_KEY=.*/SECRET_KEY=<your_value>/' .env
  1. 安装依赖包

Dify API 服务使用 Poetry 来管理依赖。您可以执行 poetry shell 来激活环境。

poetry env use 3.10
poetry install
  1. 执行数据库迁移,将数据库结构迁移至最新版本。
poetry shell
flask db upgrade
  1. 启动 API 服务
flask run --host 0.0.0.0 --port=5001 --debug

正确输出:

* Debug mode: on
INFO:werkzeug:WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
 * Running on all addresses (0.0.0.0)
 * Running on http://127.0.0.1:5001
INFO:werkzeug:Press CTRL+C to quit
INFO:werkzeug: * Restarting with stat
WARNING:werkzeug: * Debugger is active!
INFO:werkzeug: * Debugger PIN: 695-801-919

  1. 启动 Worker 服务

用于消费异步队列任务,如数据集文件导入、更新数据集文档等异步操作。 Linux / MacOS 启动:

celery -A app.celery worker -P gevent -c 1 -Q dataset,generation,mail,ops_trace --loglevel INFO

如果使用 Windows 系统启动,请替换为该命令:

celery -A app.celery worker -P solo --without-gossip --without-mingle -Q dataset,generation,mail,ops_trace --loglevel INFO
 -------------- celery@TAKATOST.lan v5.2.7 (dawn-chorus)
--- ***** ----- 
-- ******* ---- macOS-10.16-x86_64-i386-64bit 2023-07-31 12:58:08
- *** --- * --- 
- ** ---------- [config]
- ** ---------- .> app:         app:0x7fb568572a10
- ** ---------- .> transport:   redis://:**@localhost:6379/1
- ** ---------- .> results:     postgresql://postgres:**@localhost:5432/dify
- *** --- * --- .> concurrency: 1 (gevent)
-- ******* ---- .> task events: OFF (enable -E to monitor tasks in this worker)
--- ***** ----- 
 -------------- [queues]
                .> dataset          exchange=dataset(direct) key=dataset
                .> generation       exchange=generation(direct) key=generation
                .> mail             exchange=mail(direct) key=mail

[tasks]
  . tasks.add_document_to_index_task.add_document_to_index_task
  . tasks.clean_dataset_task.clean_dataset_task
  . tasks.clean_document_task.clean_document_task
  . tasks.clean_notion_document_task.clean_notion_document_task
  . tasks.create_segment_to_index_task.create_segment_to_index_task
  . tasks.deal_dataset_vector_index_task.deal_dataset_vector_index_task
  . tasks.document_indexing_sync_task.document_indexing_sync_task
  . tasks.document_indexing_task.document_indexing_task
  . tasks.document_indexing_update_task.document_indexing_update_task
  . tasks.enable_segment_to_index_task.enable_segment_to_index_task
  . tasks.generate_conversation_summary_task.generate_conversation_summary_task
  . tasks.mail_invite_member_task.send_invite_member_mail_task
  . tasks.remove_document_from_index_task.remove_document_from_index_task
  . tasks.remove_segment_from_index_task.remove_segment_from_index_task
  . tasks.update_segment_index_task.update_segment_index_task
  . tasks.update_segment_keyword_index_task.update_segment_keyword_index_task

[2024-07-31 13:58:08,831: INFO/MainProcess] Connected to redis://:**@localhost:6379/1
[2024-07-31 13:58:08,840: INFO/MainProcess] mingle: searching for neighbors
[2024-07-31 13:58:09,873: INFO/MainProcess] mingle: all alone
[2024-07-31 13:58:09,886: INFO/MainProcess] pidbox: Connected to redis://:**@localhost:6379/1.
[2024-07-31 13:58:09,890: INFO/MainProcess] celery@TAKATOST.lan ready.
  • 前端页面部署

  • 安装基础环境
    Web 前端服务启动需要用到
    Node.js v18.x (LTS)

    NPM 版本 8.x.x

    Yarn

  • 安装 NodeJS + NPM
    进入
    https://nodejs.org/en/download,选择对应操作系统的
    v18.x 以上的安装包下载并安装,建议 stable 版本,已自带 NPM。


    1. 进入 web 目录,安装依赖包

    cd web
    npm install
    

    1. 配置环境变量。在当前目录下创建文件 .env.local,并复制.env.example中的内容。根据需求修改这些环境变量的值:

    #For production release, change this to PRODUCTION
    NEXT_PUBLIC_DEPLOY_ENV=DEVELOPMENT
    #The deployment edition, SELF_HOSTED
    NEXT_PUBLIC_EDITION=SELF_HOSTED
    #The base URL of console application, refers to the Console base URL of WEB service if console domain is
    #different from api or web app domain.
    #example: http://cloud.dify.ai/console/api
    NEXT_PUBLIC_API_PREFIX=http://localhost:5001/console/api
    #The URL for Web APP, refers to the Web App base URL of WEB service if web app domain is different from
    #console or api domain.
    #example: http://udify.app/api
    NEXT_PUBLIC_PUBLIC_API_PREFIX=http://localhost:5001/api
    
    #SENTRY
    NEXT_PUBLIC_SENTRY_DSN=
    NEXT_PUBLIC_SENTRY_ORG=
    NEXT_PUBLIC_SENTRY_PROJECT=
    

    1. 构建代码,启动 web 服务

    npm run build
    
    npm run start
    #or
    yarn start
    #or
    pnpm start
    
    

    • 终端会输出如下信息:

    ready - started server on 0.0.0.0:3000, url: http://localhost:3000
    warn  - You have enabled experimental feature (appDir) in next.config.js.
    warn  - Experimental features are not covered by semver, and may cause unexpected or broken application behavior. Use at your own risk.
    info  - Thank you for testing `appDir` please leave your feedback at https://nextjs.link/app-feedback
    
  • 访问 Dify

在浏览器中输入
http://localhost
访问 Dify。访问
http://127.0.0.1:3000
即可使用本地部署的 Dify。

2.3 单独启动前端 Docker 容器

当单独开发后端时,可能只需要源码启动后端服务,而不需要本地构建前端代码并启动,因此可以直接通过拉取 docker 镜像并启动容器的方式来启动前端服务,以下为具体步骤:

  • 直接使用 DockerHub 镜像
docker run -it -p 3000:3000 -e CONSOLE_API_URL=http://127.0.0.1:5001 -e APP_API_URL=http://127.0.0.1:5001 langgenius/dify-web:latest
  • 源码构建 Docker 镜像


    1. 构建前端镜像

    cd web && docker build . -t dify-web
    

    1. 启动前端镜像

    docker run -it -p 3000:3000 -e CONSOLE_API_URL=http://127.0.0.1:5001 -e APP_API_URL=http://127.0.0.1:5001 dify-web
    

    1. 当控制台域名和 Web APP 域名不一致时,可单独设置 CONSOLE_URL 和 APP_URL
      本地访问
      http://127.0.0.1:3000

3. Ollama 部署的本地模型

Ollama 是一个开源框架,专为在本地机器上便捷部署和运行大型语言模型(LLM)而设计。,这是 Ollama 的官网地址:
https://ollama.com/

  • 以下是其主要特点和功能概述:


    1. 简化部署:Ollama 目标在于简化在 Docker 容器中部署大型语言模型的过程,使得非专业用户也能方便地管理和运行这些复杂的模型。
    2. 轻量级与可扩展:作为轻量级框架,Ollama 保持了较小的资源占用,同时具备良好的可扩展性,允许用户根据需要调整配置以适应不同规模的项目和硬件条件。
    3. API支持:提供了一个简洁的 API,使得开发者能够轻松创建、运行和管理大型语言模型实例,降低了与模型交互的技术门槛。
    4. 预构建模型库:包含一系列预先训练好的大型语言模型,用户可以直接选用这些模型应用于自己的应用程序,无需从头训练或自行寻找模型源

3.1 一键安装

curl: (77) error setting certificate verify locations:CAfile: /data/usr/local/anaconda/ssl/cacert.pemCApath: none
报错原因: cacert.pem 的寻址路径 CAfile 不对,也就是在该路径下找不到文件。

  • 解决方法:
  1. 找到你的 cacert.pem 文件所在位置 /path/to/cacert.pem。如果你没有该证书,可以先在
    https://curl.se/ca/cacert.pem
    下载,保存在某个目录中。
  2. 设置环境变量
export CURL_CA_BUNDLE=/path/to/cacert.pem
#将"/path/to/cacert.pem"替换为你的证书文件的实际路径。
export CURL_CA_BUNDLE=/www/anaconda3/anaconda3/ssl/cacert.pem
  • 执行下载
curl -fsSL https://ollama.com/install.sh | sh

3.2 手动安装

ollama中文网:
https://ollama.fan/getting-started/linux/

  1. 下载 ollama 二进制文件:Ollama 以自包含的二进制文件形式分发。将其下载到您的 PATH 中的目录:
sudo curl -L https://ollama.com/download/ollama-linux-amd64 -o /usr/bin/ollama

sudo chmod +x /usr/bin/ollama
  1. 将 Ollama 添加为启动服务(推荐):为 Ollama 创建一个用户:
sudo useradd -r -s /bin/false -m -d /usr/share/ollama ollama

3.在 /etc/systemd/system/ollama.service 中创建一个服务文件:

#vim ollama.service 

[Unit]

Description=Ollama Service
After=network-online.target

[Service]
ExecStart=/usr/bin/ollama serve
User=ollama
Group=ollama
Restart=always
RestartSec=3

[Install]
WantedBy=default.target
  1. 然后启动服务:
sudo systemctl enable ollama
  1. 启动 Ollama¶
    使用 systemd 启动 Ollama:
sudo systemctl start ollama
  1. 更新,查看日志
#再次运行
sudo curl -L https://ollama.com/download/ollama-linux-amd64 -o /usr/bin/ollama
sudo chmod +x /usr/bin/ollama

#要查看作为启动服务运行的 Ollama 的日志,请运行:
journalctl -u ollama
  1. 步骤7:关闭 Ollama 服务
#关闭ollama服务
service ollama stop

3.3 Linux内网离线安装Ollama

  1. 查看服务器CPU的型号
##查看Linux系统CPU型号命令,我的服务器cpu型号是x86_64
lscpu
  1. 步骤2:根据CPU型号下载Ollama安装包,并保存到目录

下载地址:
https://github.com/ollama/ollama/releases/

#x86_64 CPU选择下载ollama-linux-amd64
#aarch64|arm64 CPU选择下载ollama-linux-arm64

#有网机器下载过来也一样
wget https://ollama.com/download/ollama-linux-amd64 

下载到离线服务器上:/usr/bin/ollama ollama就是你下载的ollama-linux-amd64 改名了(mv),其他步骤一致

3.4 修改存储路径

Ollama模型默认存储在:

  • macOS: ~/.ollama/models
  • Linux: /usr/share/ollama/.ollama/models
  • Windows: C:\Users<username>.ollama\models

如果 Ollama 作为 systemd 服务运行,则应使用以下命令设置环境变量systemctl:

  1. 通过调用 来编辑 systemd 服务systemctl edit ollama.service。这将打开一个编辑器。

  2. Environment对于每个环境变量,在部分下添加一行[Service]:

直接在“/etc/systemd/system/ollama.service”增了2行:

[Service]
Environment="OLLAMA_HOST=0.0.0.0:7861"
Environment="OLLAMA_MODELS=/www/algorithm/LLM_model/models"
  1. 保存并退出。

  2. 重新加载systemd并重新启动 Ollama:

systemctl restart ollama

参考链接:
https://github.com/ollama/ollama/blob/main/docs/faq.md

  1. 使用 systemd 启动 Ollama:
sudo systemctl start ollama
  1. 终止

终止(ollama加载的大模型将会停止占用显存,此时ollama属于失联状态,部署和运行操作失效,会报错:

Error: could not connect to ollama app, is it running?需要启动后,才可以进行部署和运行操作

systemctl stop ollama.service
  • 终止后启动(启动后,可以接着使用ollama 部署和运行大模型)
systemctl start ollama.service

3.5 启动LLM

  • 下载模型
ollama pull llama3.1
ollama pull qwen2

  • 运行大模型
ollama run llama3.1
ollama run qwen2

  • 查看是否识别到大模型:
    ollama list
    , 如果成功, 则会看到大模型
ollama list
NAME            ID              SIZE    MODIFIED    
qwen2:latest    e0d4e1163c58    4.4 GB  3 hours ago
  • 使用该
    ollama ps
    命令查看当前已加载到内存中的模型。
NAME            ID              SIZE    PROCESSOR       UNTIL              
qwen2:latest    e0d4e1163c58    5.7 GB  100% GPU        3 minutes from now
  • nvidia-smi查看
+---------------------------------------------------------------------------------------+
| NVIDIA-SMI 535.86.10              Driver Version: 535.86.10    CUDA Version: 12.2     |
|-----------------------------------------+----------------------+----------------------+
| GPU  Name                 Persistence-M | Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp   Perf          Pwr:Usage/Cap |         Memory-Usage | GPU-Util  Compute M. |
|                                         |                      |               MIG M. |
|=========================================+======================+======================|
|   0  Tesla V100-SXM2-32GB           On  | 00000000:00:08.0 Off |                    0 |
| N/A   35C    P0              56W / 300W |   5404MiB / 32768MiB |      0%      Default |
|                                         |                      |                  N/A |
+-----------------------------------------+----------------------+----------------------+
                                                                                         
+---------------------------------------------------------------------------------------+
| Processes:                                                                            |
|  GPU   GI   CI        PID   Type   Process name                            GPU Memory |
|        ID   ID                                                             Usage      |
|=======================================================================================|
|    0   N/A  N/A   3062036      C   ...unners/cuda_v11/ollama_llama_server     5402MiB |
+---------------------------------------------------------------------------------------+
  • 启动后,我们可验证是否可用:
curl http://10.80.2.195:7861/api/chat -d '{
  "model": "llama3.1",
  "messages": [
    { "role": "user", "content": "why is the sky blue?" }
  ]
}'

3.6 更多其他配置

Ollama 可以设置的环境变量

  • OLLAMA_HOST
    :这个变量定义了Ollama监听的网络接口。通过设置OLLAMA_HOST=0.0.0.0,我们可以让Ollama监听所有可用的网络接口,从而允许外部网络访问。

  • OLLAMA_MODELS
    :这个变量指定了模型镜像的存储路径。通过设置OLLAMA_MODELS=F:\OllamaCache,我们可以将模型镜像存储在E盘,避免C盘空间不足的问题。

  • OLLAMA_KEEP_ALIVE
    :这个变量控制模型在内存中的存活时间。设置OLLAMA_KEEP_ALIVE=24h可以让模型在内存中保持24小时,提高访问速度。

  • OLLAMA_PORT
    :这个变量允许我们更改Ollama的默认端口。例如,设置OLLAMA_PORT=8080可以将服务端口从默认的11434更改为8080。

  • OLLAMA_NUM_PARALLEL
    :这个变量决定了Ollama可以同时处理的用户请求数量。设置OLLAMA_NUM_PARALLEL=4可以让Ollama同时处理两个并发请求。

  • OLLAMA_MAX_LOADED_MODELS
    :这个变量限制了Ollama可以同时加载的模型数量。设置OLLAMA_MAX_LOADED_MODELS=4可以确保系统资源得到合理分配。

Environment="OLLAMA_PORT=9380" 没有用

  • 这样指定:
    Environment="OLLAMA_HOST=0.0.0.0:7861"

  • 指定 GPU
    本地有多张 GPU,如何用指定的 GPU 来运行 Ollama? 在Linux上创建如下配置文件,并配置环境变量 CUDA_VISIBLE_DEVICES 来指定运行 Ollama 的 GPU,再重启 Ollama 服务即可【测试序号从0还是1开始,应是从0开始】。

vim /etc/systemd/system/ollama.service
[Service]
Environment="CUDA_VISIBLE_DEVICES=0,1"

3.7 Ollama常见命令

  1. 重启 ollama
systemctl daemon-reload
systemctl restart ollama
  1. 重启 ollama 服务

ubuntu/debian

sudo apt update
sudo apt install lsof
stop ollama
lsof -i :11434
kill <PID>
ollama serve


  • Ubuntu
sudo apt update
sudo apt install lsof
stop ollama
lsof -i :11434
kill <PID>
ollama serve

  1. 确认服务端口状态:
netstat -tulpn | grep 11434

  1. 配置服务

为使外网环境能够访问到服务,需要对 HOST 进行配置。

打开配置文件:

vim /etc/systemd/system/ollama.service

根据情况修改变量 Environment:

服务器环境下:

Environment="OLLAMA_HOST=0.0.0.0:11434"

虚拟机环境下:

Environment="OLLAMA_HOST=服务器内网IP地址:11434"

3.8 卸载Ollama

如果决定不再使用Ollama,可以通过以下步骤将其完全从系统中移除:

(1)停止并禁用服务:

sudo systemctl stop ollama
sudo systemctl disable ollama

(2)删除服务文件和Ollama二进制文件:

sudo rm /etc/systemd/system/ollama.service 
sudo rm $(which ollama)

(3)清理Ollama用户和组:

sudo rm -r /usr/share/ollama
sudo userdel ollama
sudo groupdel ollama

通过以上步骤,不仅能够在Linux平台上成功安装和配置Ollama,还能够灵活地进行更新和卸载。

4.配置LLM+Dify

  • 确认服务端口状态:
netstat -tulnp | grep ollama
#netstat -tulpn | grep 11434

  • 报错: "Error: could not connect to ollama app, is it running?"

参考链接:
https://stackoverflow.com/questions/78437376/run-ollama-run-llama3-in-colab-raise-err-error-could-not-connect-to-ollama

/etc/systemd/system/ollama.service文件是:

[Service]
ExecStart=/usr/local/bin/ollama serve
Environment="OLLAMA_HOST=0.0.0.0:7861"
Environment="OLLAMA_KEEP_ALIVE=-1"
  • 运行指令
export OLLAMA_HOST=0.0.0.0:7861
ollama list
ollama run llama3.1

#直接添加到环境变量也可以
vim ~/.bashrc 
source ~/.bashrc

在 设置 > 模型供应商 > Ollama 中填入:

  • 模型名称:llama3.1

  • 基础 URL:
    http://<your-ollama-endpoint-domain>:11434


    • 此处需填写可访问到的 Ollama 服务地址。
    • 若 Dify 为 docker 部署,建议填写局域网 IP 地址,如:
      http://10.80.2.195:11434
      或 docker 宿主机 IP 地址,如:
      http://172.17.0.1:11434
    • 若为本地源码部署,可填写
      http://localhost:11434
  • 模型类型:对话

  • 模型上下文长度:4096


    • 模型的最大上下文长度,若不清楚可填写默认值 4096。
  • 最大 token 上限:4096


    • 模型返回内容的最大 token 数量,若模型无特别说明,则可与模型上下文长度保持一致。
  • 是否支持 Vision:是


    • 当模型支持图片理解(多模态)勾选此项,如 llava。
  • 点击 "保存" 校验无误后即可在应用中使用该模型。

  • Embedding 模型接入方式与 LLM 类似,只需将模型类型改为 Text Embedding 即可。

  • 如果您使用Docker部署Dify和Ollama,您可能会遇到以下错误:
httpconnectionpool(host=127.0.0.1, port=11434): max retries exceeded with url:/cpi/chat (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7f8562812c20>: fail to establish a new connection:[Errno 111] Connection refused'))

httpconnectionpool(host=localhost, port=11434): max retries exceeded with url:/cpi/chat (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7f8562812c20>: fail to establish a new connection:[Errno 111] Connection refused'))

这个错误是因为 Docker 容器无法访问 Ollama 服务。localhost 通常指的是容器本身,而不是主机或其他容器。要解决此问题,您需要将 Ollama 服务暴露给网络。

4.1.多模型对比

参考单个模型部署一样,进行再一次配置添加即可

  • 需要注意的是添加完新的模型配置后,需要刷新dify网页,直接网页端刷新就好,新添加的模型就会加载进来

  • 可以看到调用后模型资源消耗情况

更多推荐

更多优质内容请关注公号:汀丶人工智能;会提供一些相关的资源和优质文章,免费获取阅读。

更多优质内容请关注CSDN:汀丶人工智能;会提供一些相关的资源和优质文章,免费获取阅读。