PostgreSQL码农集散地

自建私有化OpenAI服务

参考文档点击文末阅读原文打开; 推荐《最好的PostgreSQL学习镜像》;


自建OpenAI服务

数据库和大模型结合, 可以实现很多场景的应用, 例如

  • 社交场景、电商用户评价的情感词实时计算(好评、中评、差评).
  • 将私有化文本存储在数据库中, 并计算其向量值建立向量索引, 在基于问题生成文本时使用向量索引快速检索与问题相关的私有文本片段, 实现RAG
  • 将会话历史存储于数据库中, 并计算其向量值建立向量索引, 在调用大语言模型与用户进行交互时, 从历史会话中搜索相关内容, 作为上下文信息辅助文本生成, 实现大模型外脑记忆

但是, 有些情况你可能无法使用云端大语言模型服务(例如openai), 例如如下情况

  • 大语言模型云服务在远程, 你的业务可能与之网络不通, 无法调用
  • 敏感数据可能泄露给openai服务, 所以不允许使用openai服务

此时, 你可能需要自建openai服务, 可以使用ollam.

下面将使用例子简单分享一下, 使用openai+http插件让PostgreSQL快捷使用openai/自建openai服务

  • 远程openai服务 -> 数据库内 文本 - to - embedding vector
  • 远程openai服务 -> 数据库内 文本实时分析 (例如 情感词分类)
  • 本地/自建 llm 服务 -> 数据库内 文本 - to - embedding vector
  • 本地/自建 llm 服务 -> 数据库内 文本实时分析 (例如 情感词分类)

使用到如下组件

  • ollama
  • large language model
  • postgresql
  • openai
  • http

例子

1、ollama 部署很简单, 参考下文

  • 《AI大模型+全文检索+tf-idf+向量数据库+我的文章 系列之1 - 低配macbook成功跑AI大模型LLama3:8b, 感谢ollama》
  • 《OLLAMA 环境变量/高级参数配置 : 监听 , 内存释放窗口 , 常用设置举例》

拉取几个模型试试

ollama pull llama3.2:3b  
ollama pull mxbai-embed-large:latest  

2、设置环境变量, 让ollama监听0.0.0.0地址, 位于容器内的PG/PolarDB数据库可以宿主机上的ollama服务

Open your terminal.  

  Set the environment variable using launchctl:  
  launchctl setenv OLLAMA_HOST "0.0.0.0"

  Restart the Ollama application to apply the changes.  

确认ollama 11434端口监听正常

U-4G77XXWF-1921:~ digoal$ nc -v 127.0.0.1 11434  
Connection to 127.0.0.1 port 11434 [tcp/*] succeeded!  
^C  
U-4G77XXWF-1921:~ digoal$ nc -v xxx.221.xxx.xxx 11434  
Connection to xxx.221.xxx.xxx port 11434 [tcp/*] succeeded!  
^C  

3、启动数据库, 我使用了下面的容器, 你也可以自己安装

4、进入容器并编译openai插件

docker exec -ti pg bash  
cd /tmp  
git clone --depth 1 https://github.com/pramsey/pgsql-openai  
cd pgsql-openai  
USE_PGXS=1 make install  

5、安装http和openai插件

psql  

  create extension http ;  
create extension openai ;  

openai有3个接口函数, 分别用于查询当前支持哪些模型, 基于提示词生成文本, 基于文本生成向量

  • openai.models() returns setof record. Returns a listing of the AI models available via the API.
  • openai.prompt(context text, query text, [model text]) returns text. Set up context and then pass in a starting prompt for the model.
  • openai.vector(query text, [model text]) returns text. For use with embedding models ( Ollama, OpenAI ) only, returns a JSON-formatted float array suitable for direct input into pgvector. Using non-embedding models to generate embeddings will result in extremely poor search results.

openai函数接口详情

postgres=# \df openai.*  
                                                                          List of functions  
 Schema |  Name  |                                Result data type                                 |                   Argument data types                    | Type   
--------+--------+---------------------------------------------------------------------------------+----------------------------------------------------------+------  
 openai | models | TABLE(id text, object text, created timestamp without time zone, owned_by text) |                                                          | func  
 openai | prompt | text                                                                            | context text, prompt text, model text DEFAULT NULL::text | func  
 openai | vector | text                                                                            | input text, model text DEFAULT NULL::text                | func  
(3 rows)  

注意http插件可以设置http请求超时, 默认可能是5秒, 如果大模型的硬件较差, 响应可能会超时报错, 你可以使用如下函数进行设置

SELECT http_set_curlopt('CURLOPT_TIMEOUT', '10');  -- 设置为10秒  

试一试这几个openai接口函数

首先需要设置几个会话变量(注意 提示词模型选哪个? 文本转向量的模型选哪个? 取决于你下载了哪些模型.), 让数据库知道去哪里调用大语言模型. 或者你也可以把会话变量设置到参数文件、user 配置、database 配置中.

psql  

  -- 设置当前会话  
SET openai.api_uri = 'http://xxx.221.xxx.xxx:11434/v1/';  
SET openai.api_key = 'none';  
SET openai.prompt_model = 'llama3.2:3b';  
SET openai.embedding_model = 'mxbai-embed-large';  

  or  

  -- 设置到某个database到配置中, 下次连接这个数据库时会自动配置这些项  
alter database postgres set openai.api_uri = 'http://xxx.221.xxx.xxx:11434/v1/';  
alter database postgres SET openai.api_key = 'none';  
alter database postgres SET openai.prompt_model = 'llama3.2:3b';  
alter database postgres SET openai.embedding_model = 'mxbai-embed-large';  

  postgres=# select * from pg_db_role_setting ;  
 setdatabase | setrole |                                                                  setconfig                                                                     
-------------+---------+----------------------------------------------------------------------------------------------------------------------------------------------  
       13757 |       0 | {openai.api_uri=http://xxx.221.xxx.xxx:11434/v1/,openai.api_key=none,openai.prompt_model=llama3.2:3b,openai.embedding_model=mxbai-embed-large}  
(1 row)  

然后就可以调用openai的接口函数了

-- 查询当前支持哪些模型  
postgres=# SELECT * FROM openai.models();  
            id            | object |       created       | owned_by   
--------------------------+--------+---------------------+----------  
 llama3.1:8b              | model  | 2024-11-21 06:43:41 | library  
 llama3.2:3b              | model  | 2024-11-21 06:12:14 | library  
 mxbai-embed-large:latest | model  | 2024-11-21 06:02:27 | library  
 qwen2.5-coder:14b        | model  | 2024-11-15 07:07:01 | library  
 mistral-small:22b        | model  | 2024-09-19 02:36:41 | library  
(5 rows)  

  -- 将文本转换为向量  
SELECT openai.vector('A lovely orange pumpkin pie recipe.');  

  [-0.021690376, 0.003092674, -0.00023757249, 0.0059805233,   
 0.0024175171, 0.013349159, 0.006348481, 0.016774092,   
 0.0051014116, 0.026803626, 0.015113969, 0.0031985058,  
  ...   
 -0.020051343, 0.006571748, 0.008234819, 0.010086719,   
 -0.0071006618, -0.020877795, -0.022467814, 0.010012546,   
 0.0008801813, -0.0006236545, 0.016922941, -0.011781357]  

  -- 基于提示词生成文本  
SELECT openai.prompt(  
  'You are an advanced sentiment analysis model. Read the given   
   feedback text carefully and classify it as one of the   
   following sentiments only: "positive", "neutral", or   
   "negative". Respond with exactly one of these words   
   and no others, using lowercase and no punctuation'
,  
  'I enjoyed the setting and the service and the bisque was   
   great.'
 );  

    prompt    
----------  
 positive  

6、设计一个表, 存储客户反馈, 以及对应的情感词

CREATE TABLE feedback (  
    feedback text, -- freeform comments from the customer  
    sentiment text -- positive/neutral/negative from the LLM  
    );  

创建一个触发器函数, 在插入以上表时自动触发, 调用大语言模型, 生成feedback字段内容对应的情感词(正面、中性、反面)

--  
-- Step 1: Create the trigger function  
--  
CREATE OR REPLACE FUNCTION analyze_sentiment() RETURNS TRIGGER AS $$  
DECLARE  
    response TEXT;  
BEGIN  
    -- Use openai.prompt to classify the sentiment as positive, neutral, or negative  
    response := openai.prompt(  
        'You are an advanced sentiment analysis model. Read the given feedback text carefully and classify it as one of the following sentiments only: "positive", "neutral", or "negative". Respond with exactly one of these words and no others, using lowercase and no punctuation',  
        NEW.feedback  
    );  

      -- Set the sentiment field based on the model's response  
    NEW.sentiment := response;  

      RETURN NEW;  
END;  
$$ LANGUAGE '

plpgsql';  

  --  
-- Step 2: Create the trigger to execute the function before each INSERT or UPDATE  
--  
CREATE TRIGGER set_sentiment  
    BEFORE INSERT OR UPDATE ON feedback  
    FOR EACH ROW  
    EXECUTE FUNCTION analyze_sentiment();  

插入数据, 并查询调用大模型计算情感词的效果如下

INSERT INTO feedback (feedback)  
    VALUES  
        ('The food was not well cooked and the service was slow.'),  
        ('I loved the bisque but the flan was a little too mushy.'),  
        ('This was a wonderful dining experience, and I would come again,  
          even though there was a spider in the bathroom.'
);  

  postgres=# select * from feedback ;  
                            feedback                             | sentiment   
-----------------------------------------------------------------+-----------  
 The food was not well cooked and the service was slow.          | negative  
 I loved the bisque but the flan was a little too mushy.         | negative  
 This was a wonderful dining experience, and I would come again,+| positive  
           even though there was a spider in the bathroom.       |   
(3 rows)  

  postgres=# INSERT INTO feedback (feedback) values ('我讨厌吸烟, 危害健康');  
INSERT 0 1  
postgres=# INSERT INTO feedback (feedback) values ('少量喝酒, 对身体可能有好处');  
INSERT 0 1
postgres=# INSERT INTO feedback (feedback) values ('今天天气很不错, 非常适合跑步');
INSERT 0 1
postgres=# INSERT INTO feedback (feedback) values ('西湖的游客很多, 特别是国庆节的时候, 断桥都要被人踩断了');
INSERT 0 1
postgres=# select * from feedback ;
                            feedback                             | sentiment 
-----------------------------------------------------------------+-----------
 The food was not well cooked and the service was slow.          | negative
 I loved the bisque but the flan was a little too mushy.         | negative
 This was a wonderful dining experience, and I would come again,+| positive
           even though there was a spider in the bathroom.       | 
 我讨厌吸烟, 危害健康                                            | negative
 少量喝酒, 对身体可能有好处                                      | neutral
 今天天气很不错, 非常适合跑步                                    | positive
 西湖的游客很多, 特别是国庆节的时候, 断桥都要被人踩断了          | negative
(7 rows)

在实际使用中, 可能在应用收到客户请求后塞到消息队列, 从消息队列获取并调用大模型计算情感词可能更好.  因为调用模型计算是较耗时的过程, 长期占用数据库链接、长事务有很多副作用.

参考

  • https://ollama.com/library/llama3.2
  • https://www.devbookmarks.com/p/ollama-answer-bind-to-0-0-0-0-cat-ai
  • https://github.com/pramsey/pgsql-openai
  • https://github.com/pramsey/pgsql-http
  • https://www.crunchydata.com/blog/accessing-large-language-models-from-postgresql
  • 《OLLAMA 环境变量/高级参数配置 : 监听 , 内存释放窗口 , 常用设置举例》
  • 《AI大模型+全文检索+tf-idf+向量数据库+我的文章 系列之1 - 低配macbook成功跑AI大模型LLama3:8b, 感谢ollama》
  • 《用“大参数模型”和“特定领域内容”fine-tuning提升“小参数模型的RAG性能”》
  • 《Elasticsearch vs Paradedb pg_search - RAG绝配: PostgreSQL 混合搜索插件(全文检索+语义(向量)检索)》
  • 《提升RAG召回效果的方法探讨》
  • 《介绍一个开源项目 RAGflow : 基于深度文档理解构建的开源 RAG》
  • 《AI大模型+全文检索+tf-idf+向量数据库+我的文章 系列之4 - RAG 自动提示微调(prompt tuning)》
  • https://en.wikipedia.org/wiki/Retrieval-augmented_generation

今日荐书

彩蛋:国产数据库周边生态

当然一款数据库要流行起来, 除了自己要强大, 还离不开生态. 用好周边生态工具, 管理水平战胜90%老司机!!! 下面简单介绍一下国产数据库周边生态.

1、管控软件

鸣嵩(前阿里云数据库总经理 / 研究员)等大佬们创业创办的云猿生, 核心产品是KubeBlocks. 他们的理念是让管理数据库和搭积木一样简单, 如果你要管理很多套并且种类(OLTP\OLAP\NoSQL\KV\TS\MQ等)很多的数据库产品, 推荐首选.

  • https://github.com/apecloud/kubeblocks

PG中文社区核心委员唐成老师的公司乘数开源的Clup, 专用管理PostgreSQL和PolarDB的集群管理软件, 如果你要管理很多套数据库, 推荐选择. 并且Clup还提供了企业版、自研的连接池、分布式存储、一体机、备份平台等, 是企业用户推荐之选.

  • https://www.csudata.com/

若航开源的pigsty, 集成了300多个PG插件的PG集群和PolarDB集群管理软件, 如果你要管理很多套PG或PolarDB数据库, 且对插件有特别多的需求, 推荐选择.

  • https://pigsty.cc/zh/

2、审计监控诊断优化

翟总(曾经是我背后的男人)到海信聚好看后研发的 DBdoctor, 采用ebpf技术, 在对数据库几乎没有影响的情况下实时监控数据库和服务器的各项指标, 发现和诊断问题根因非常方便.

  • https://www.dbdoctor.cn/

天舟老哥的核心产品Bytebase 是位于您和数据库之间的中间件。它是数据库 DevOps 的 GitLab/GitHub,专为开发人员、DBA 和平台工程师打造。

  • https://bytebase.cc/docs/introduction/what-is-bytebase/

PawSQL, SQL优化和诊断产品.  

D-Smart, Oracle老前辈白老大出品, 专注企业级市场, 将业界顶级DBA经验的产品化作品, 产品功能包括数据库监控、诊断、优化等.

  • https://www.modb.pro/db/567140

3、国产数据库IDE

IDE是开发者的必备工具,例如社区有pgAdmin, 国产IDE则可以看看老程序猿达刚老师的DeskUI:

  • https://www.deskui.com

4、数据同步&迁移&备份恢复

NineData, 老领导出去创业做的产品, 产品涵盖了数据同步、迁移、备份、比对、devops、chatDBA等.

  • https://www.ninedata.cloud/home

DSG, 非常老牌的数据库同步迁移企业级产品, 支持各种数据库的异构和同构迁移, 用他们的话说, 没有dsg搞不定的迁移, 比goldengate还牛.

  • https://www.dsgdata.com/

公开课

如果你对PolarDB学习感兴趣可以阅读这个公开课系列:

除了PolarDB还非常值得关注的几款PG栈国产数据库:

  • HaloDB(基于PG兼容PostgreSQL、Oracle、MySQL. http://www.halodbtech.com/ )、
  • IvorySQL(基于开源PG兼容PG、Oracle. https://www.ivorysql.org/zh-cn/ )、
  • ProtonBase(云原生分布式数仓. https://protonbase.com/ )、
  • 成都文武数据库(https://ww-it.cn)

参考文档点击阅读原文获得


感谢关注我的github (https://github.com/digoal/blog) 及视频号:

Image