吴忠躺衫网络科技有限公司

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

用C++構建自己的GPT文檔工具

jf_WZTOguxH ? 來源:InfoQ ? 2023-08-19 14:20 ? 次閱讀

作者 | Michael Haephrati、Ruth Haephrati 譯者 | 劉雅夢 策劃 | Tina

雖然通過 Web 界面使用 ChatGPT 是一回事,但創建自己的自主 AI 工具,并通過其 API 與 ChatGPT 交互,則完全是另一回事,特別是當你的目標是保持對用戶交互的完全控制時。與此同時,作為一名堅定 C++ 的支持者,我們相信用 C++ 編寫的 GPT 工具能減輕處理(無休止的)編輯批注這一艱巨任務所帶來的痛苦。

總體思路

我們旨在探索 MS Office 的自動化領域,并利用 ChatGPT API 增強編輯過程。我們設想了一個復雜的工具,可以將 C++ 與 ChatGPT API 無縫地集成,從而提供一種與 Word 文檔中的編輯批注進行交互的新方法。

傳統的文檔編輯包括手動審閱內容和向特定部分添加批注。就我們而言,當我們編寫 C++ 書籍時,我們每次都會遇到 100 多條編輯批注,其中大部分與出版商的風格指南和注釋有關。如果能有一種方法將這些批注和相關文本存儲在數據庫中,那就太好了,更不用說基于人工智能的編輯潛力了。這正是我們的軟件所要實現的目標:通過自動化這一過程,我們可以加快編輯工作流程。雖然這個工具可以作為概念驗證(POC),不建議用于編寫和編輯整本書,但它仍然是一個令人興奮的自動化練習,當然值得一試。

它是如何做到的

工作流程從我們的軟件掃描 Word 文件開始,使用 Office Automation API 仔細檢查文檔中嵌入的每一條編輯批注。

枚舉完所有批注后,我們的工具就會提取它們以及與之相關的文本段,并將它們存儲在 sqlite3 數據庫中。在此基礎上,它將圍繞如何改進或修復文本的特定部分來為 ChatGPT 準備有針對性的問題。通過利用 ChatGPT API,我們可以利用語言模型的豐富知識和語言能力來獲取專家的意見和建議。

在收到 ChatGPT 的回復之后,我們的工具會動態地將建議的編輯內容合并到相關的文本片段中,從而根據模型的見解無縫地增強內容。

這種自動化的編輯過程大大減少了手工工作量,并加快了文檔的整體細化完善。我們的工具甚至可以跟蹤更改,但要記得在完成后關閉“跟蹤更改”。

編程方面,我們的項目中有幾個構建塊,其中一些可以擴展或替換以滿足不同的目的。我們將我們的代碼稱為概念驗證( Proof of Concept, POC)。

構建塊

以下是這一過程的參與者——我們的構建塊:

Chat GPT API

我們的工具通過使用各種參數和方法來與 ChatGPT 進行接口調用和交互。我們準備要發送給 API 的有效負載并解析響應。要使用我們的工具,必須要獲取一個 API 密鑰并將其添加到我們的代碼中,注意不是“”。下面的代碼片段演示了與 ChatGPT 交互的基礎知識。

使用 API 的優勢包括:能夠與 Chat GPT 進行接口調用和交互,并使用不同的參數和方法,準備要發送到 API 的有效負載,以及解析返回給我們的響應。

使用 ChatGPT API 時,需要考慮以下幾點。

我們的通用函數

為了本文的目的,我們創建了一個通用函數。該函數是模塊化的,因為它能生成具有模塊化屬性和參數的請求,格式如下:

data =
{
    {"messages", json::array({{ {"role", "user"}, {"content", entire_converstaion_string} }})},
    {"model", model},
    {"temperature", temperature},
    {"max_tokens", max_tokens},
    {"n", n},
    {"stop", stop}
};

讓我們來看看這些屬性,并討論下它們存在的問題及需求:

“messages”——定義用戶和模型之間的對話歷史。對話中的每條消息都由兩個屬性組成:“role”(可以是“system”、“user”或“assistant”)和“content”(消息的實際文本內容)。為了本文的目的,我們使用了“user”

“model”——允許指定想要使用的 ChatGPT 模型版本。在本文中,我們使用了“gpt-3.5-turbo”

“temperature”——可以設置它來控制生成的文本和 prompt 之間的相似程度。例如,高溫值可用于生成與 prompt 更不同的文本,而低溫值可用于生成與 prompt 更相似的文本。在目標為生成與給定輸入相似但具有一定程度的變化或“創造性”文本的情況下,這可能很有用。

“max_tokens”——是每個請求使用的最大 token 數。處理的 token 數量取決于輸入和輸出文本的長度。

1-2 句~= 30 個 token

1 段~=100 個 token

1,500 個單詞~=2048 個 token

作為 ChatGPT API 的用戶,我們需要為我們消耗的 token 付費。

3721384e-3e52-11ee-ac96-dac502259ad0.png

“n”——控制模型應提供的響應數量;默認情況下,它被設置為 1,即單個響應

“stop”——表示應觸發模型停止生成其響應的字符串。默認情況下設置為換行符。這意味著,當模型在其輸出中遇到新行時,它將在那之后停止生成。

我們的 Prompt

我們總是喜歡說,結構良好的 prompt 的重要性是怎么強調也不為過的。精心構建的 prompt 可以作為指導藍圖,影響生成的輸出質量。在本文中,我們將深入研究有效 prompt 的組成部分,并提供實際的示例和指導,幫助 C++ 學生在項目中最大限度地發揮 ChatGPT API 的潛力。

下面是一個例子:

// 為GPT請求設置prompt 
wstring prompt{ L"I will send you some text, and an associated comment that tells what changes need to be made in the text. Please start your response with 'Changed text: ' followed by the actual updated text. Here is the original text: '" };
prompt += rangeText;
prompt += L"'. And here is the associated comment suggesting the change: '";
prompt += commentText;
prompt += L"'. Please do not respond with anything else, only include the changed text and nothing else. If you do not have the correct answer or don't know what to say, respond with these exact words: 'I do not understand";
//

在編寫 prompt 時,最好創建一個模板,其中包含將在整個程序中使用的請求的常量部分,然后根據當前需要更改可變部分。以下是一個良好的 prompt 的一些關鍵組成部分:

上下文:

上下文作為 prompt 的基礎,能提供關鍵的背景信息。它使語言模型能夠掌握任務的本質。無論是簡明扼要的問題描述還是相關細節的總結,對提供上下文都至關重要。

示例:

“你是一名軟件開發人員,正在為外賣服務開發移動應用程序。該應用程序旨在為用戶提供從當地餐館訂餐的無縫體驗。作為開發過程的一部分,你需要幫助生成有關該應用程序的功能是如何吸引人的信息豐富內容。”

任務:

任務定義了 prompt 的精確目標或目的。它應該清晰、簡潔,并重點關注于 ChatGPT 模型預期的具體信息或操作。

示例:“寫一個簡短的段落,突出應用程序的主要功能,并展示它們是如何增強客戶的送餐體驗的。”

約束條件:

約束為 prompt 設置了邊界或限制。它們可能包括特定的要求、對響應長度或復雜性的限制或任何其他相關約束。通過定義約束,可以引導生成的輸出滿足所需的結果。

示例:

“回答應該簡明扼要,字數不超過 150 字。重點關注應用程序區別于競爭對手的最突出功能,并使其對用戶友好。”

補充說明:

在本節中,你將有機會提供補充上下文或指定所需的輸出格式。這可以包括有關預期輸入格式或請求以特定格式(如 Markdown 或 JSON)輸出的詳細信息。

示例:“請將響應格式化為 JSON 對象,其中包含每個特性描述的鍵值對。每個鍵都應代表一個特性,其對應的值應提供一個簡短的描述,突出其優點。”

通過理解和實現這些基本組件,C++ 開發人員可以掌握構建有效 prompt 的藝術,以便在項目中最優地利用 ChatGPT API。深思熟慮地結合上下文,定義明確的任務,設置約束并提供額外的說明將使開發人員能夠獲得精確且高質量的結果。

連續的聊天

在大多數情況下,我們希望能從你上次結束的地方繼續對話。Chat GPT API 使用了一個特殊的標志來實現這一點。如果未設置,將會發生如下的情況:

? 法國的首都是哪里?

Request payload: '{"messages":[{"content":"what is the capital of france?","role":"user"}],"model":"gpt-3.5-turbo"}'


Callback JSON: '{"id":"chatcmpl-7AlP3bJX2T7ibomyderKHwT7fQkcN","object":"chat.completion","created":1682799853,"model":"gpt-3.5-turbo-0301","usage":{"prompt_tokens":15,"completion_tokens":7,"total_tokens":22},"choices":[{"message":{"role":"assistant","content":"The capital of France is Paris."},"finish_reason":"stop","index":0}]}

你人工智能朋友的回答是:

? 法國的首都是巴黎。

接下來的一個問題是:

? 它有多大?

Request payload: '{"messages":[{"content":"How big is it?","role":"user"}],"model":"gpt-3.5-turbo"}'


Callback JSON: '{"id":"chatcmpl-7AlPAabscfyDrAV2wTjep0ziiseEB","object":"chat.completion","created":1682799860,"model":"gpt-3.5-turbo-0301","usage":{"prompt_tokens":13,"completion_tokens":20,"total_tokens":33},"choices":[{"message":{"role":"assistant","content":"I apologize, but I need more context to accurately answer your question. What are you referring to?"},"finish_reason":"stop","index":0}]}

? 我很抱歉,但是我需要更多的上下文來準確回答你的問題。你指的是什么?

要解決這一問題,我們需要保持連續的聊天,但我們該如何做到這一點呢?事實上,要做到這一點的唯一方法是必須來回傳遞一個包含整個對話的字符串。

string entire_converstaion_string;

我們還定義了:

 using Conversation = vector;

它的定義是:

using SingleExchange = pair;

在我們的源代碼中,你可以看到我們是如何將 Conversation 對象維護成固定長度的(很明顯,我們無法存儲無休止的對話)。這個固定長度是在這里設置的:

int conversation_exchange_limit{ 100 };

如前所述,我們的 prompt 在請求的效率中起著關鍵作用,當涉及到連續聊天時,我們可能需要使用不同的 prompt:

    string prompt_start{ "You are a chatbot. I want to have a conversation 
with you where you can remember the context between multiple requests. To do 
that, I will send all previous request prompts and your corresponding 
responses, please use those as context. All the previous request prompts and 
the current will have the 'request: ' before it, and all your corresponding 
responses will have 'response: ' before it. Your job is to respond to only the 
latest request. Do not add anything by yourself, just respond to the latest 
request. Starting now

" };
多部分響應

當你問你的人工智能朋友:

? 給我寫一段 C++ 代碼,實現從 1 到 10 的計數。

你可能會得到這樣的結果:

? 當然可以,下面是從 1 到 10 計數的 C++ 代碼:

沒有任何源代碼。

原因如下:發送給 API 的 stop 參數讓模型知道它應該在輸出的哪個點上停止生成更多內容。當沒有指定任何內容時,換行符就是默認值,這意味著模型在輸出第一個換行符后就停止生成更多的輸出。

但是,如果你將“stop”參數設置為空字符串,你將得到完整的響應,其中將包含源代碼:

37301292-3e52-11ee-ac96-dac502259ad0.jpg

關于 OLE 自動化

OLE 自動化是微軟在過去引入的一項技術,此后不斷發展。在我們的實現中,我們直接使用了 Microsoft 自動化,繞過了 MFC(Microsoft Foundation Classes,微軟基礎類庫)的使用。為了訪問 MS Word 的各種元素,如文檔、活動文檔、批注等,我們為需要交互的每個對象定義了 IDispatch COM 接口。

Office 自動化

我們的工具自動化了 MS Word 中的各種任務和特性。它可以讀取批注、查找相關文本、打開 / 關閉“跟蹤更改”、在后臺工作、替換文本、添加批注、保存結果以及關閉文檔。下面是我們所使用的函數的描述:

OLEMethod():一個輔助函數,用于調用 IDispatch 接口上的方法,處理方法調用并返回指示錯誤的 HRESULT 值。

Initialize():該函數通過創建 Word 應用程序的實例并設置其可見性來初始化 OfficeAutomation 類。它能初始化 COM 庫,檢索 Word 應用程序的 CLSID,創建應用程序的實例,并設置其可見性。

OfficeAutomation():OfficeAutomation 類的構造函數。它初始化成員變量,并使用 false 調用 Initialize 函數以創建不可見的 Word 應用程序實例。

~OfficeAutomation():OfficeAutomation 類的析構函數。它在此實現中不執行任何操作。

SetVisible():設置活動文檔可見性的函數。它使用一個布爾參數來確定文檔是否應該可見。它使用 OLEMethod 函數來設置 Word 應用程序的可見性屬性。

OpenDocument():打開 Word 文檔并設置其可見性的函數。它接受一個指向文檔路徑和一個用于可見性的布爾參數。如果需要,它會初始化該類,檢索 Documents 接口,打開指定的文檔,并設置其可見性。

CloseActiveDocument():關閉活動文檔的函數。它會保存文檔,然后關閉文檔。它使用 OLEMethod 函數來調用適當的方法。

ToggleTrackChanges():用于切換活動文檔的“跟蹤修訂”特性的函數。它獲取特性的當前狀態,并在必要時進行切換。它使用 OLEMethod 函數來訪問和修改“TrackRevisions”屬性。

FindCommentsAndReply():該函數用于查找活動文檔中的所有批注,向 ChatGPT API 發送請求以獲取建議,并根據 API 響應更新每個批注的關聯文本。它遍歷每個批注,檢索關聯的文本范圍,用文本和批注作為上下文向 ChatGPT API 發送 prompt,接收 API 響應,并使用建議的更改更新文本范圍。

CountDocuments():該函數用于返回與 OfficeAutomation 類關聯的 Word 應用程序中打開的文檔數。它檢索 Documents 接口并返回計數。

處理批注

在制定審查批注機制時,我們需要能夠枚舉所有批注,并區分已處理的批注和未處理的批注。

這可以通過以下方式完成:

bool IsCommentResolved(IDispatch* pComment)
{
        // 檢查批注是否被解析
        VARIANT isResolved;
        VariantInit(&isResolved);
        HRESULT hr = OLEMethod(DISPATCH_PROPERTYGET, &isResolved, pComment,             (LPOLESTR)L"Done", 0);




    if (FAILED(hr)) 
    {
        ShowError(hr);
        return false;
    }
    bool resolved = (isResolved.vt == VT_BOOL && isResolved.boolVal == VARIANT_TRUE);
    return resolved;
}

正如你所看到的,使用 OLEMethod() 和 DISPATCH_PROPERTYGET,我們可以檢查屬性名“Done”,它表示已處理的批注。

枚舉批注

接下來,我們可以枚舉文檔中的所有批注,并打印每個批注的“已處理”(“Resolved”)狀態。

在開始之前,我們不僅要枚舉批注,還要枚舉與之相關的文本。原因在于批注的最初目的。文檔的作者撰寫并編輯文檔。編輯標記一個片段,可以是一個段落、一個句子甚至是一個單詞,并添加一條批注。當我們閱讀批注時,我們需要該批注的上下文,而上下文就是那個被標記的片段。

因此,當我們枚舉所有批注時,我們不僅要打印批注本身,還要打印與之相關的文本(我們的片段)。

當我們開始檢查所有批注時,我們需要聲明并初始化 2 個指針:

pComments——指向文檔的批注。

pRange——指向文檔的內容(包含與批注相關聯的文本的段)。

它們兩個都需被初始化:

{
    VARIANT result;
    VariantInit(&result);
    m_hr = OLEMethod(DISPATCH_PROPERTYGET, &result, m_pActiveDocument, (LPOLESTR)L"Comments", 0);
    if (FAILED(m_hr))
    {
        ShowError(m_hr);
        return m_hr;
    }




    pComments = result.pdispVal;
}




{
    VARIANT result;
    VariantInit(&result);
    m_hr = OLEMethod(DISPATCH_PROPERTYGET, &result, m_pActiveDocument, (LPOLESTR)L"Content", 0);
    if (FAILED(m_hr))
    {
        ShowError(m_hr);
        return m_hr;
    }
    pRange = result.pdispVal;
}

然后我們就可以開始循環遍歷文檔中的所有批注了。

你可以在我們的源代碼中看到這是如何實現的,但一般來說,我們從批注開始,轉到相關的文本,并檢查批注是否得到了處理。然后,我們就可以將其打印到報告中,將其添加到數據庫中,或者將其發送給 Chat GPT API。

API 接口通用代碼

為了通過網絡與任何 API 接口,我們使用了通用代碼來方便地發送請求并使用 JSON 數據格式解析響應。在此過程中,我們使用了 libCurl,這是一個強大的工具,被廣泛用于使用命令行或腳本在網絡上傳輸數據。它在不同領域有著廣泛的應用,包括汽車、電視、路由器、打印機、音頻設備、移動設備、機頂盒和媒體播放器等領域。它是眾多軟件應用程序的互聯網傳輸引擎,安裝量達數十億次。

如果你查看了我們的源代碼,就可以看到 libCurl 是如何使用的。

總 結

通過利用 MS Office 自動化的強大功能并將其與 ChatGPT API 集成,我們使編輯和作者能夠簡化其工作流程,節省寶貴的時間并提高他們的工作質量。C++ 和 ChatGPT API 之間的協作促進了流暢高效的交互,使我們的工具能夠為每個編輯批注提供智能且感知上下文的建議。

因此,我們的小型 MS Office 自動化 POC 工具,由 ChatGPT API 和 C++ 支持,徹底改變了編輯過程。通過自動提取編輯批注,與 ChatGPT 互動以尋求專家指導,并無縫集成編輯建議,我們使用戶能夠提高他們在 Word 文檔中工作的質量和效率。這種強大的技術組合為高效的文檔編輯開辟了新的可能性,并代表著 MS Office 自動化領域的重大飛躍。

審核編輯:湯梓紅

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 字符串
    +關注

    關注

    1

    文章

    585

    瀏覽量

    20601
  • C++
    C++
    +關注

    關注

    22

    文章

    2114

    瀏覽量

    73854
  • 模型
    +關注

    關注

    1

    文章

    3305

    瀏覽量

    49217
  • GPT
    GPT
    +關注

    關注

    0

    文章

    360

    瀏覽量

    15505
  • ChatGPT
    +關注

    關注

    29

    文章

    1568

    瀏覽量

    8055

原文標題:用 C++構建自己的 GPT 文檔工具

文章出處:【微信號:AI前線,微信公眾號:AI前線】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    自己C++編寫的一個STM32小庫

    目前也就實現了GPIO和RCC的控制吧...C++對象編程感覺比C編程清晰的多,估計我的水平效率也低得多...不過比原生庫更方便,代碼量更小.有興趣的可以下載下來看看,我在這里就放
    發表于 08-14 19:15

    RealView編譯工具4.0版基本指南

    RVCT由一套工具以及支持文檔和示例組成。 這些工具使您能夠為ARM系列處理器編寫和構建應用程序。 您可以使用RVCT
    發表于 08-12 07:33

    Visual C++做數據庫開發

    實驗 Visual C++做數據庫開發 一、實驗目的1、了解數據庫的訪問方式,掌握ADO 方式訪問數據庫2、 Visual C++制作簡單的數據
    發表于 05-10 10:54 ?2461次閱讀

    使用Nios II軟件構建工具

    使用Nios II軟件構建工具 This chapter describes the Nios II Software Build Tools (SBT), a set of utilities
    發表于 10-17 15:49 ?20次下載

    Visual C++編程技術文檔

    Visual C++編程技術文檔!資料來源網絡,如有侵權,敬請見諒
    發表于 11-20 15:00 ?0次下載

    使用C++構建嵌入式開發框架

    使用C++構建嵌入式開發框架
    發表于 10-25 11:25 ?17次下載
    使用<b class='flag-5'>C++</b><b class='flag-5'>構建</b>嵌入式開發框架

    C++入門教程之C++程序設計的課件資料免費下載

    文檔的主要內容詳細介紹的是C++入門教程之C++程序設計的課件資料免費下載主要內容包括了:1. 認識C++2. C++的現狀和發展3.
    發表于 12-07 08:00 ?33次下載
    <b class='flag-5'>C++</b>入門教程之<b class='flag-5'>C++</b>程序設計的課件資料免費下載

    VISUAL C++教程之VISUAL C++的安裝和使用方法

    文檔的主要內容詳細介紹的是VISUAL C++教程之VISUAL C++的安裝和使用方法資料免費下載。
    發表于 12-27 16:32 ?19次下載
    VISUAL <b class='flag-5'>C++</b>教程之VISUAL <b class='flag-5'>C++</b>的安裝和使用方法

    C++程序設計教程之C++工具的詳細資料說明

    文檔的詳細介紹的是C++程序設計教程之C++工具的詳細資料說明主要內容包括了:1. 異常處理,2. 命名空間,3. 使用早期的函數庫
    發表于 03-14 16:39 ?4次下載
    <b class='flag-5'>C++</b>程序設計教程之<b class='flag-5'>C++</b><b class='flag-5'>工具</b>的詳細資料說明

    C++程序設計的基礎知識初步了解C++的資料免費下載

    文檔的主要內容詳細介紹的是C++程序設計的基礎知識初步了解C++的資料免費下載包括了:1 認識C++,2 C++的現狀和發展,3
    發表于 06-10 08:00 ?25次下載
    <b class='flag-5'>C++</b>程序設計的基礎知識初步了解<b class='flag-5'>C++</b>的資料免費下載

    如何用Bazel構建C++項目

    眾所周知,C/C++ 語言具備很強可移植性,作為高級的底層語言能兼容各式各樣的系統環境或應用。因此很多企業更偏向于將算法 C/C++ 實現
    的頭像 發表于 11-18 17:23 ?5201次閱讀

    C++ STM32 編程 005 c++編寫STM32程序的準備

    ? ? ? ? 由于我們使用的是 ARM 的工具鏈 是gcc的,所以,我們大可以c++來編寫程序,無論是 c++99 或c++11 還是
    發表于 12-02 14:36 ?5次下載
    <b class='flag-5'>C++</b> STM32 編程 005 <b class='flag-5'>用</b><b class='flag-5'>c++</b>編寫STM32程序的準備

    qtC++寫的2048小游戲源代碼

    qtC++寫的2048小游戲源代碼
    發表于 09-27 11:48 ?3次下載

    C++構建并復制二叉樹

    使用C++構建一個二叉樹并復制、輸出。
    的頭像 發表于 01-10 15:17 ?1077次閱讀
    <b class='flag-5'>C++</b><b class='flag-5'>構建</b>并復制二叉樹

    GNU構建裸機系統

    構建和安裝GNU工具鏈,但是很難找到一個將GNU C/C++工具鏈用于裸機ARM系統的綜合例子,該系統將具有現實項目中所需的所有基本特性。
    發表于 10-16 17:34 ?0次下載
    金龙博彩| 24山亥山巳向造葬日课| 江口县| 永利赌场| 威尼斯人娱乐城优惠条件| 百家乐官网视频对对碰| 金龙娱乐城| 德州扑克怎么玩| 全讯网3344111| 博狗百家乐的玩法技巧和规则| 百家乐关键词| 百家乐哪条路好| 百家乐官网发牌| 百家乐官网现金网最好的系统哪里有可靠吗 | 玩百家乐官网有几种公式| 百家乐官网神算子| 澳门百家乐官网真人娱乐城| 网络百家乐会作假吗| 半圆百家乐桌子| 金沙百家乐娱乐城场| 百家乐娱乐城新澳博| 百家乐赌博技巧网| 百家乐扎金花斗地主| 百家乐英皇赌场娱乐网规则| 百家乐娱乐平台真钱游戏| 优惠搏百家乐的玩法技巧和规则 | 先锋百家乐的玩法技巧和规则| 百家乐赌术大揭秘| 百家乐博彩平| 威尼斯人娱乐城微博| 大发888真钱娱乐城下载| 最新娱乐城注册送彩金| 平昌县| 玩德州扑克技巧| 监利县| 百家乐官网视频对对碰| 沙龙百家乐官网娱乐网| 百家乐下注平台| 新锦江百家乐娱乐平台| 百家乐统计软件| 大发888赌场网址|