軟件工程師在這個世界上占據(jù)著令人興奮的地位。無論技術(shù)堆棧或行業(yè)如何,我們的任務(wù)都是解決直接有助于實(shí)現(xiàn)雇主目標(biāo)的問題。作為獎勵,我們可以利用技術(shù)來緩解我們遇到的任何挑戰(zhàn)。

對于這個例子,我想重點(diǎn)關(guān)注 pgvector(Postgres 的開源矢量相似性搜索)如何實(shí)現(xiàn)用于識別企業(yè)數(shù)據(jù)中存在的數(shù)據(jù)相似性。

一個簡單的用例

舉一個簡單的例子,我們假設(shè)營銷部門需要為他們計劃發(fā)起的活動提供幫助。目標(biāo)是覆蓋與軟件行業(yè)密切相關(guān)的行業(yè)中的所有 Salesforce 帳戶。

最后,他們希望重點(diǎn)關(guān)注前三個最相似行業(yè)的客戶,以便將來能夠使用此工具來查找其他行業(yè)的相似之處。如果可能的話,他們希望能夠提供所需數(shù)量的匹配行業(yè),而不是總是返回前三名。

高級設(shè)計

此用例以執(zhí)行相似性搜索為中心。雖然可以手動完成此練習(xí),但我會想到 Wikipedia2Vec 工具,因為已經(jīng)預(yù)先訓(xùn)練好的嵌入為多種語言創(chuàng)建。詞嵌入(也稱為向量)是包含句法和語義信息的詞的數(shù)字表示。通過將單詞表示為向量,我們可以從數(shù)學(xué)上確定哪些單詞在語義上與其他單詞“更接近”。

在我們的示例中,我們還可以編寫一個簡單的 Python 程序來為 Salesforce 中配置的每個行業(yè)創(chuàng)建詞向量。

pgvector 擴(kuò)展需要 Postgres 數(shù)據(jù)庫。但是,我們示例的企業(yè)數(shù)據(jù)當(dāng)前駐留在 Salesforce 中。幸運(yùn)的是,Heroku Connect 提供了一種將 Salesforce 帳戶與 Heroku Postgres 同步的簡單方法,將其存儲在名為 <代碼> salesforce.account 。然后,我們將有另一個名為 salesforce.industries 的表,其中包含 Salesforce 中的每個行業(yè)(作為 VARCHAR 鍵)及其關(guān)聯(lián)的詞向量。

借助 Postgres 中的 Salesforce 數(shù)據(jù)和詞向量,我們將使用 Java 和 Spring Boot 創(chuàng)建一個 RESTful API。該服務(wù)將執(zhí)行必要的查詢,并以 JSON 格式返回結(jié)果。

我們可以這樣說明解決方案的高級視圖:

源代碼將駐留在 GitLab 中。發(fā)出 git push heroku 命令將觸發(fā) Heroku 中的部署,從而引入營銷團(tuán)隊可以輕松使用的 RESTful API。

構(gòu)建解決方案

高層設(shè)計到位后,我們就可以開始構(gòu)建解決方案了。使用 Salesforce 登錄,我能夠?qū)Ш降?strong>帳戶屏幕來查看此練習(xí)的數(shù)據(jù)。以下是企業(yè)數(shù)據(jù)首頁的示例:

創(chuàng)建 Heroku 應(yīng)用程序

為此,我計劃使用 Heroku 來解決營銷團(tuán)隊的請求。我登錄到 Heroku 帳戶并使用創(chuàng)建新應(yīng)用程序按鈕建立一個名為 similarity-search-sfdc 的新應(yīng)用程序:

創(chuàng)建應(yīng)用程序后,我導(dǎo)航到資源選項卡以查找 Heroku Postgres 插件。我在附加組件搜索字段中輸入了“Postgres”。

從列表中選擇Heroku Postgres后,我選擇了Standard 0計劃,但pgvector是可在運(yùn)行 PostgreSQL 15 或 beta Essential 層數(shù)據(jù)庫的標(biāo)準(zhǔn)層(或更高)數(shù)據(jù)庫產(chǎn)品上使用

當(dāng)我確認(rèn)該附加組件時,Heroku 生成并提供了一個 DATABASE_URL 連接字符串。我在應(yīng)用程序的設(shè)置選項卡的配置變量部分中找到了它。我使用此信息連接到我的數(shù)據(jù)庫并啟用 pgvector 擴(kuò)展,如下所示:

?

創(chuàng)建擴(kuò)展向量;

接下來,我搜索并找到了 Heroku Connect 插件。我知道這將為我提供一種連接到 Salesforce 中的企業(yè)數(shù)據(jù)的簡單方法。

對于本練習(xí),免費(fèi)的演示版計劃效果很好。

此時,similarity-search-sfdc 應(yīng)用的資源選項卡如下所示:

我按照“設(shè)置 Heroku Connect”說明鏈接了我的Heroku Connect 的 Salesforce 帳戶。然后,我選擇了 Account 對象進(jìn)行同步。完成后,我能夠在 Heroku Connect 和底層 Postgres 數(shù)據(jù)庫中看到相同的 Salesforce 帳戶數(shù)據(jù)。

從 SQL 角度來看,我所做的結(jié)果是創(chuàng)建了一個具有以下設(shè)計的 salesforce.account 表:

SQL

?

創(chuàng)建表 salesforce.account
(
    創(chuàng)建日期時間戳,
    已刪除布爾值,
    名稱 varchar(255),
    systemmodstamp 時間戳,
    帳號 varchar(40),
    行業(yè) varchar(255),
    sfid varchar(18),
    序列號
        首要的關(guān)鍵,
    _hc_lastop varchar(32),
    _hc_err 文本
);

生成向量

為了使相似性搜索按預(yù)期運(yùn)行,我需要為每個 Salesforce 帳戶行業(yè)生成詞向量:

  • 服裝
  • 銀行業(yè)務(wù)
  • 生物技術(shù)
  • 施工
  • 教育
  • 電子產(chǎn)品
  • 工程
  • 娛樂
  • 食品和飲料
  • 財務(wù)
  • 政府
  • 醫(yī)療保健
  • 熱情好客
  • 保險
  • 媒體
  • 非營利性
  • 其他
  • 休閑
  • 零售
  • 運(yùn)送
  • 技術(shù)
  • 電信
  • 交通
  • 實(shí)用程序

由于主要用例表明需要找到軟件行業(yè)的相似之處,因此我們也需要為該行業(yè)生成一個詞向量。

為了使本練習(xí)保持簡單,我使用 Python 3.9 和一個名為 embed.py 的文件手動執(zhí)行此任務(wù),如下所示:

Python

?

從 wikipedia2vec 導(dǎo)入 Wikipedia2Vec
wiki2vec = Wikipedia2Vec.load('enwiki_20180420_100d.pkl')
print(wiki2vec.get_word_vector('軟件').tolist())

請注意 – get_word_vector() 方法需要使用小寫字母表示行業(yè)。

運(yùn)行 python embed.pysoftware 單詞生成以下單詞向量:

?

[-0.40402618050575256、0.5711150765419006、-0.7885153293609619、-0.15960034728050232、-0.5692323446273804、
0.005377458408474922、-0.1315757781267166、-0.16840921342372894、0.6626015305519104、-0.26056772470474243、
0.3681095242500305、-0.453583300113678、0.004738557618111372、-0.4111144244670868、-0.1817493587732315、
-0.9268549680709839、0.07973367720842361、-0.17835664749145508、-0.2949991524219513、-0.5533796548843384、
0.04348105192184448, -0.028855713084340096, -0.13867013156414032, -0.6649054884910583, 0.03129105269908905,
-0.24817068874835968、0.05968991294503212、-0.24743635952472687、0.20582349598407745、0.6240783929824829、
0.3214546740055084、-0.14210252463817596、0.3178422152996063、0.7693028450012207、0.2426985204219818、
-0.6515568494796753、-0.2868216037750244、0.3189859390258789、0.5168254971504211、0.11008890718221664、
0.3537853956222534、-0.713259220123291、-0.4132286608219147、-0.026366405189037323、0.003034653142094612、
-0.5275223851203918、-0.018167126923799515、0.23878540098667145、-0.6077089905738831、0.5368344187736511、
-0.1210874393582344、0.26415619254112244、-0.3066694438457489、0.1471938043832779、0.04954215884208679、
0.2045321762561798、0.1391817331314087、0.5286830067634583、0.5764685273170471、0.1882934868335724、
-0.30167853832244873、-0.2122340053319931、-0.45651525259017944、-0.016777794808149338、0.45624101161956787、
-0.0438646525144577, -0.992512047290802, -0.3771328926086426, 0.04916151612997055, -0.5830298066139221,
-0.01255014631897211、0.21600870788097382、-0.18419665098190308、0.1754663586616516、-0.1499166339635849、
-0.1916201263666153、-0.22884036600589752、0.17280352115631104、0.25274306535720825、0.3511175513267517、
-0.20270302891731262、-0.6383468508720398、0.43260180950164795、-0.21136239171028137、-0.05920517444610596、
0.7145522832870483、0.7626600861549377、-0.5473887920379639、0.4523043632507324、-0.1723199188709259、
-0.10209759324789047、-0.5577948093414307、-0.10156919807195663、0.31126976013183594、0.3604489266872406、
-0.13295558094978333、0.2473849356174469、0.278846800327301、-0.28618067502975464、0.00527254119515419]

創(chuàng)建行業(yè)表

為了存儲詞向量,我們需要使用以下 SQL 命令向 Postgres 數(shù)據(jù)庫添加一個 industries 表:

SQL

?

創(chuàng)建表 salesforce.industries
(
    name varchar not null 約束 Industries_pk 主鍵,
    嵌入向量(100)不為空
);

創(chuàng)建industries表后,我們將插入每個生成的詞向量。我們使用類似于以下的 SQL 語句來執(zhí)行此操作:

SQL

?

插入 salesforce.industries
(名稱、嵌入)
價值觀
    ('軟件','[-0.40402618050575256, 0.5711150765419006, -0.7885153293609619, -0.15960034728050232, -0.5692323446273804, 0.00537745840 8474922, -0.1315757781267166, -0.16840921342372894, 0.6626015305519104, -0.26056772470474243, 0.3681095242500305, -0.453583300113 678, 0.004738557618111372, -0.4111144244670868, -0.1817493587732315, -0.9268549680709839, 0.07973367720842361, -0.17835664749145508, -0.2949991524219513, -0.5533796548843384, 0.04348105192184448, -0.028855713084340096 , -0.13867013156414032, -0.6649054884910583, 0.03129105269908905, -0.24817068874835968, 0.05968991294503212, -0.24743635952472687 , 0.20582349598407745, 0.6240783929824829, 0.3214546740055084, -0.14210252463817596, 0.3178422152996063, 0.7693028450012207, 0 .2426985204219818,-0.6515568494796753, -0.2868216037750244、0.3189859390258789、0.5168254971504211、0.11008890718221664、0.3537853956222534、-0.713259220123291、-0.4 132286608219147, -0.026366405189037323, 0.003034653142094612, -0.5275223851203918, -0.018167126923799515, 0.23878540098667145, -0 .6077089905738831, 0.5368344187736511, -0.1210874393582344, 0.26415619254112244, -0.3066694438457489, 0.1471938043832779, 0.049 54215884208679, 0.2045321762561798, 0.1391817331314087 , 0.5286830067634583, 0.5764685273170471, 0.1882934868335724, -0.30167853832244873, -0.2122340053319931, -0.45651525259017944, -0.016777794808149338, 0.45624101161956787, -0.0438646525144577, -0.992512047290802, -0.3771328926086426, 0.04916151612997055, -0 .5830298066139221, -0.01255014631897211, 0.21600870788097382, -0.18419665098190308, 0.1754663586616516, -0.1499166339635849, -0.1 916201263666153 , -0.22884036600589752, 0.17280352115631104, 0.25274306535720825, 0.3511175513267517, -0.20270302891731262, -0.638346850872039 8, 0.43260180950164795, -0.21136239171028137, -0.05920517444610596, 0.7145522832870483, 0.7626600861549377, -0.5473887920379639, 0.4523043632507324, -0.1723199188709259, -0.10209759324789047, -0.5577948093414307, -0.10156919807195663, 0.31126976013183594, 0 .3604489266872406,- 0.13295558094978333、0.2473849356174469、0.278846800327301、-0.28618067502975464、0.00527254119515419]
');

請注意 – 雖然我們使用小寫代表軟件行業(yè)(軟件)創(chuàng)建了詞向量,但 industries.name 列需要與大寫行業(yè)相匹配名稱(軟件)。

將所有生成的詞向量添加到 industries 表后,我們就可以將重點(diǎn)轉(zhuǎn)向引入 RESTful API。

引入 Spring Boot 服務(wù)

此時,我作為一名軟件工程師的熱情開始高漲,因為我已經(jīng)做好了一切準(zhǔn)備來解決眼前的挑戰(zhàn)。

接下來,使用 Spring Boot 3.2.2 和 Java (temurin) 17,我在 IntelliJ IDEA 中創(chuàng)建了 similarity-search-sfdc 項目,并具有以下 Maven 依賴項:

XML

?

<依賴項> <依賴關(guān)系> org.springframework.boot spring-boot-starter-actuator <依賴關(guān)系> org.springframework.boot spring-boot-starter-data-jpa <依賴關(guān)系> org.springframework.boot spring-boot-starter-web <依賴關(guān)系> com.pgvector pgvector <版本>0.1.4 <依賴關(guān)系> org.postgresql postgresql <范圍>運(yùn)行時 <依賴關(guān)系> org.springframework.boot spring-boot-configuration-processor <可選>true <依賴關(guān)系> org.projectlombok 龍目島 <可選>true <依賴關(guān)系> org.springframework.boot spring-boot-starter-test <范圍>測試

我為 Account 對象和 Industry(嵌入)對象創(chuàng)建了簡化的實(shí)體,這些實(shí)體與之前創(chuàng)建的 Postgres 數(shù)據(jù)庫表對齊。

爪哇

?

@AllArgsConstructor
@NoArgs構(gòu)造函數(shù)
@數(shù)據(jù)
@實(shí)體
@Table(名稱=“帳戶”,模式=“銷售人員”)
公開課賬戶{
    @ID
    @Column(名稱=“sfid”)
    私有字符串 ID;
    私有字符串名稱;
    私營弦產(chǎn)業(yè);
}

@AllArgsConstructor
@NoArgs構(gòu)造函數(shù)
@數(shù)據(jù)
@實(shí)體
@Table(名稱=“行業(yè)”,模式=“銷售人員”)
公開課行業(yè){
    @ID
    私有字符串名稱;
}

使用 JpaRepository 接口,我添加了以下擴(kuò)展以允許輕松訪問 Postgres 表:

爪哇

?

(選擇嵌入
來自 salesforce.industries
WHERE 名稱 = ‘軟件’)
限制 3)
按名稱排序;” data-lang=”text/x-sql”>

SELECT sfid、名稱、行業(yè)
來自 salesforce.account
哪里的行業(yè)
  輸入(選擇名稱
      來自 salesforce.industries
      WHERE 名稱 != '軟件'
      按嵌入排序
        <->(選擇嵌入
             來自 salesforce.industries
             WHERE 名稱 = '軟件')
      限制 3)
按名稱排序;

從那里,我構(gòu)建了 AccountsService 類來與 JPA 存儲庫交互:

爪哇

?

@RequiredArgsConstructor @服務(wù) 公共類 AccountsService { 私人最終賬戶存儲庫賬戶存儲庫; 私有最終IndustryRepository IndustriesRepository; 公共集<帳戶> getAccountsBySimilarIndustry(字符串行業(yè), 整數(shù)限制) 拋出異常{ List<行業(yè)> Industries = IndustriesRepository.findAll(); 如果(行業(yè) 。溪流() .map(行業(yè)::getName) .anyMatch(行業(yè)::等于)) { 返回賬戶存儲庫 .findSimilaritiesForIndustry(行業(yè),限制); } 別的 { 拋出新的異常( “無法定位'”+行業(yè)+“'行業(yè)”); } } }

最后,我讓 AccountsController 類提供 RESTful 入口點(diǎn)并連接到 AccountsService

爪哇

?

curl --location 'https://HEROKU-APP-ROOT-URL/accounts/similarities?industry=Software&limit=3'

RESTful API 返回 200 OK HTTP 響應(yīng)狀態(tài)以及以下負(fù)載:

JSON

?

[
    {
        “id”:“001Kd00001bsP80IAE”,
        "name": "CleanSlate 科技集團(tuán)",
        “行業(yè)”:“技術(shù)”
    },
    {
        “id”:“001Kd00001bsPBFIA2”,
        “名稱”:“CMG 全球”,
        “行業(yè)”:“媒體”
    },
    {
        “id”:“001Kd00001bsP8AIAU”,
        "name": "開發(fā)者聚光燈",
        “行業(yè)”:“技術(shù)”
    },
    {
        “id”:“001Kd00001bsP8hIAE”,
        "name": "蛋頭",
        “行業(yè)”:“電子”
    },
    {
        “id”:“001Kd00001bsP85IAE”,
        “名稱”:“Marqeta”,
        “行業(yè)”:“技術(shù)”
    }
]

因此,技術(shù)媒體電子行業(yè)是與最接近的行業(yè)本例中的軟件行業(yè)。

現(xiàn)在,營銷部門有了一份可以聯(lián)系以開展下一次營銷活動的帳戶列表。

結(jié)論

幾年前,我花在玩軍團(tuán)要塞 2多人視頻游戲上的時間比我愿意承認(rèn)的還要多。這是 2012 年一次非常有趣的活動的屏幕截圖:

那些熟悉我生活這方面的人可能會告訴你,我默認(rèn)選擇的玩家職業(yè)是士兵。這是因為士兵的生命值、移動力、速度和火力具有最佳的平衡。

我覺得軟件工程師就是現(xiàn)實(shí)世界中的“士兵階層”,因為我們可以適應(yīng)任何情況,專注于高效地提供滿足期望的解決方案。

幾年來,我一直專注于以下使命宣言,我認(rèn)為它可以適用于任何 IT 專業(yè)人員:

<塊引用>

“將時間集中在提供可擴(kuò)展知識產(chǎn)權(quán)價值的特性/功能上。利用框架、產(chǎn)品和服務(wù)來完成其他一切。”

– J.維斯特

在本文的示例中,我們能夠利用 Heroku Connect 將企業(yè)數(shù)據(jù)與 Postgres 數(shù)據(jù)庫同步。安裝 pgvector 擴(kuò)展后,我們從這些 Salesforce 帳戶中為每個獨(dú)特的行業(yè)創(chuàng)建了詞向量。最后,我們引入了 Spring Boot 服務(wù),該服務(wù)簡化了查找行業(yè)與另一個行業(yè)最接近的 Salesforce 帳戶的過程。

我們利用現(xiàn)有的開源技術(shù)、添加的小型 Spring Boot 服務(wù)和 Heroku PaaS 快速解決了這個用例 – 完全遵循我的使命宣言。我無法想象如果沒有這些框架、產(chǎn)品和服務(wù),需要多少時間。

如果您有興趣,可以在 GitLab

祝你有美好的一天!

Comments are closed.