Bringen Sie Ihnen Schritt für Schritt bei, wie Sie mit Milvus und Towhee einen KI-Chatbot erstellen!

Als führender Anbieter von Vektordatenbanken eignet sich Milvus für eine Vielzahl von KI-Anwendungen, die effiziente und skalierbare Vektorsuchfunktionen erfordern.

Wenn Sie beispielsweise einen Datenverwaltungsprozess für einen Chatbot aufbauen möchten, muss Milvus die Vektordatenbank der Wahl sein. Um diese Anwendungsentwicklung einfacher zu verwalten und besser zu verstehen, müssen Sie Towhee ( https://towhee.io/ ) verwenden. Towhee ist ein aufstrebendes Framework für maschinelles Lernen (ML), das den Prozess der Implementierung und Orchestrierung komplexer ML-Modelle vereinfacht.

Als Nächstes werde ich vorstellen, wie man mit Milvus + Towhee einen einfachen KI-Chatbot über Python erstellt. Dieser Artikel konzentriert sich auf die Verarbeitung und Analyse unstrukturierter Daten sowie das Speichern und Abfragen von Vektordaten.

01. Richten Sie die Umgebung ein

Erstellen Sie zunächst eine virtuelle Python-Umgebung, um den Chatbot auszuführen.

Das Folgende ist eine Linux-Shell-Sitzung. Erstellen und aktivieren Sie die Umgebung mithilfe der Shell-Sitzung und aktualisieren Sie pip auf die neueste Version.

[egoebelbecker@ares milvus_chatbot]$ python -m venv ./chatbot_venv
[egoebelbecker@ares milvus_chatbot]$ source chatbot_venv/bin/activate
(chatbot_venv) [egoebelbecker@ares milvus_chatbot]$ pip install --upgrade pip
Requirement already satisfied: pip in ./chatbot_venv/lib64/python3.11/site-packages (22.2.2)
Collecting pip
  Using cached pip-23.1.2-py3-none-any.whl (2.1 MB)
Installing collected packages: pip
  Attempting uninstall: pip
    Found existing installation: pip 22.2.2
    Uninstalling pip-22.2.2:
      Successfully uninstalled pip-22.2.2
Successfully installed pip-23.1.2

Als nächstes installieren Sie die Pakete, die zum Ausführen Ihres Codes erforderlich sind: Pandas, Jupyter, Langchain, Towhee, Unstructured, Milvus, PymMilvus, sent_transformers und Gradio.

(chatbot_venv) [egoebelbecker@ares milvus_chatbot]$ pip install pandas jupyter langchain towhee unstructured milvus pymilvus sentence_transformers gradio
Collecting pandas
  Obtaining dependency information for pandas from https://files.pythonhosted.org/packages/d0/28/88b81881c056376254618fad622a5e94b5126db8c61157ea1910cd1c040a/pandas-2.0.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata
  Using cached pandas-2.0.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (18 kB)
Collecting jupyter
  Using cached jupyter-1.0.0-py2.py3-none-any.whl (2.7 kB)
(snip)
Installing collected packages: webencodings, wcwidth, pytz, pure-eval, ptyprocess, pickleshare, json5, ipython-genutils, filetype, fastjsonschema, executing, backcall, zipp, XlsxWriter, xlrd, widgetsnbextension, websocket-client, webcolors, urllib3, uri-template, tzdata, typing-extensions, traitlets, tqdm, tornado, tinycss2, tenacity, tabulate, soupsieve, sniffio, six, send2trash, rpds-py, rfc3986-validator, rfc3986, regex, pyzmq, PyYAML, python-magic, python-json-logger, pypandoc, pygments, pycparser, psutil, prompt-toolkit, prometheus-client, platformdirs, pkginfo, pillow, pexpect, parso, pandocfilters, packaging, overrides, olefile, numpy, nest-asyncio, mypy-extensions, multidict, more-itertools, mistune, mdurl, markupsafe, markdown, lxml, jupyterlab-widgets, jupyterlab-pygments, jsonpointer, joblib, jeepney, idna, greenlet, frozenlist, fqdn, et-xmlfile, docutils, defusedxml, decorator, debugpy, click, charset-normalizer, chardet, certifi, babel, attrs, async-timeout, async-lru, yarl, typing-inspect, terminado, SQLAlchemy, rfc3339-validator, requests, referencing, qtpy, python-pptx, python-docx, python-dateutil, pydantic, pdf2image, openpyxl, numexpr, nltk, msg-parser, matplotlib-inline, marshmallow, markdown-it-py, jupyter-core, jinja2, jedi, jaraco.classes, importlib-metadata, comm, cffi, bleach, beautifulsoup4, asttokens, anyio, aiosignal, stack-data, rich, requests-toolbelt, readme-renderer, pandas, openapi-schema-pydantic, langsmith, jupyter-server-terminals, jupyter-client, jsonschema-specifications, dataclasses-json, cryptography, arrow, argon2-cffi-bindings, aiohttp, SecretStorage, pdfminer.six, langchain, jsonschema, isoduration, ipython, argon2-cffi, unstructured, nbformat, keyring, ipykernel, twine, qtconsole, nbclient, jupyter-events, jupyter-console, ipywidgets, towhee, nbconvert, jupyter-server, notebook-shim, jupyterlab-server, jupyter-lsp, jupyterlab, notebook, jupyter
Successfully installed PyYAML-6.0.1 SQLAlchemy-2.0.19 SecretStorage-3.3.3 XlsxWriter-3.1.2 aiohttp-3.8.5 aiosignal-1.3.1 anyio-3.7.1 argon2-cffi-21.3.0 argon2-cffi-bindings-21.2.0 arrow-1.2.3 asttokens-2.2.1 async-lru-2.0.4 async-timeout-4.0.2 attrs-23.1.0 babel-2.12.1 backcall-0.2.0 beautifulsoup4-4.12.2 bleach-6.0.0 certifi-2023.7.22 cffi-1.15.1 chardet-5.1.0 charset-normalizer-3.2.0 click-8.1.6 comm-0.1.3 cryptography-41.0.2 dataclasses-json-0.5.14 debugpy-1.6.7 decorator-5.1.1 defusedxml-0.7.1 docutils-0.20.1 et-xmlfile-1.1.0 executing-1.2.0 fastjsonschema-2.18.0 filetype-1.2.0 fqdn-1.5.1 frozenlist-1.4.0 greenlet-2.0.2 idna-3.4 importlib-metadata-6.8.0 ipykernel-6.25.0 ipython-8.14.0 ipython-genutils-0.2.0 ipywidgets-8.0.7 isoduration-20.11.0 jaraco.classes-3.3.0 jedi-0.19.0 jeepney-0.8.0 jinja2-3.1.2 joblib-1.3.1 json5-0.9.14 jsonpointer-2.4 jsonschema-4.18.4 jsonschema-specifications-2023.7.1 jupyter-1.0.0 jupyter-client-8.3.0 jupyter-console-6.6.3 jupyter-core-5.3.1 jupyter-events-0.7.0 jupyter-lsp-2.2.0 jupyter-server-2.7.0 jupyter-server-terminals-0.4.4 jupyterlab-4.0.3 jupyterlab-pygments-0.2.2 jupyterlab-server-2.24.0 jupyterlab-widgets-3.0.8 keyring-24.2.0 langchain-0.0.248 langsmith-0.0.15 lxml-4.9.3 markdown-3.4.4 markdown-it-py-3.0.0 markupsafe-2.1.3 marshmallow-3.20.1 matplotlib-inline-0.1.6 mdurl-0.1.2 mistune-3.0.1 more-itertools-10.0.0 msg-parser-1.2.0 multidict-6.0.4 mypy-extensions-1.0.0 nbclient-0.8.0 nbconvert-7.7.3 nbformat-5.9.2 nest-asyncio-1.5.7 nltk-3.8.1 notebook-7.0.1 notebook-shim-0.2.3 numexpr-2.8.4 numpy-1.25.2 olefile-0.46 openapi-schema-pydantic-1.2.4 openpyxl-3.1.2 overrides-7.3.1 packaging-23.1 pandas-2.0.3 pandocfilters-1.5.0 parso-0.8.3 pdf2image-1.16.3 pdfminer.six-20221105 pexpect-4.8.0 pickleshare-0.7.5 pillow-10.0.0 pkginfo-1.9.6 platformdirs-3.10.0 prometheus-client-0.17.1 prompt-toolkit-3.0.39 psutil-5.9.5 ptyprocess-0.7.0 pure-eval-0.2.2 pycparser-2.21 pydantic-1.10.12 pygments-2.15.1 pypandoc-1.11 python-dateutil-2.8.2 python-docx-0.8.11 python-json-logger-2.0.7 python-magic-0.4.27 python-pptx-0.6.21 pytz-2023.3 pyzmq-25.1.0 qtconsole-5.4.3 qtpy-2.3.1 readme-renderer-40.0 referencing-0.30.0 regex-2023.6.3 requests-2.31.0 requests-toolbelt-1.0.0 rfc3339-validator-0.1.4 rfc3986-2.0.0 rfc3986-validator-0.1.1 rich-13.5.1 rpds-py-0.9.2 send2trash-1.8.2 six-1.16.0 sniffio-1.3.0 soupsieve-2.4.1 stack-data-0.6.2 tabulate-0.9.0 tenacity-8.2.2 terminado-0.17.1 tinycss2-1.2.1 tornado-6.3.2 towhee-1.1.1 tqdm-4.65.0 traitlets-5.9.0 twine-4.0.2 typing-extensions-4.7.1 typing-inspect-0.9.0 tzdata-2023.3 unstructured-0.8.7 uri-template-1.3.0 urllib3-2.0.4 wcwidth-0.2.6 webcolors-1.13 webencodings-0.5.1 websocket-client-1.6.1 widgetsnbextension-4.0.8 xlrd-2.0.1 yarl-1.9.2 zipp-3.16.2
(chatbot_venv) [egoebelbecker@ares milvus_chatbot]$

Besuchen Sie den Link https://gist.github.com/egoebelbecker/07059b88a1c4daa96ec07937f8ca77b3 , um das Jupyter-Notizbuch zu erhalten, das den gesamten Code für dieses Tutorial abdeckt. Laden Sie das Notebook herunter, starten Sie Jupyter und laden Sie das Notebook.

chatbot_venv) [egoebelbecker@ares milvus_chatbot]$ jupyter notebook milvus_chatbot.ipynb 
[I 2023-07-31 11:29:01.748 ServerApp] Package notebook took 0.0000s to import
[I 2023-07-31 11:29:01.759 ServerApp] Package jupyter_lsp took 0.0108s to import
[W 2023-07-31 11:29:01.759 ServerApp] A `_jupyter_server_extension_points` function was not found in jupyter_lsp. Instead, a `_jupyter_server_extension_paths` function was found and will be used for now. This function name will be deprecated in future releases of Jupyter Server.
[I 2023-07-31 11:29:01.764 ServerApp] Package jupyter_server_terminals took 0.0045s to import
[I 2023-07-31 11:29:01.765 ServerApp] Package jupyterlab took 0.0000s to import
[I 2023-07-31 11:29:02.124 ServerApp] Package notebook_shim took 0.0000s to import

02. Erstellen Sie einen Chatbot

Sobald alles fertig ist, können Sie den Chatbot erstellen.

Dokumentenspeicher

Der Roboter muss den Dokumentblock und den mit Towhee extrahierten Dokumentblockvektor speichern. In diesem Schritt müssen wir Milvus verwenden.

Installieren Sie die Lightweight-Version von Milvus Lite und führen Sie den Milvus-Server mit dem folgenden Befehl aus:

(chatbot_venv) [egoebelbecker@ares milvus_chatbot]$ milvus-server

    __  _________ _   ____  ______
   /  |/  /  _/ /| | / / / / / __/
  / /|_/ // // /_| |/ / /_/ /\ \
 /_/  /_/___/____/___/\____/___/ {Lite}

 Welcome to use Milvus!

 Version:   v2.2.12-lite
 Process:   139309
 Started:   2023-07-31 12:43:43
 Config:    /home/egoebelbecker/.milvus.io/milvus-server/2.2.12/configs/milvus.yaml
 Logs:      /home/egoebelbecker/.milvus.io/milvus-server/2.2.12/logs

 Ctrl+C to exit …

Oder führen Sie den Code im Notebook aus:

from milvus import default_server

# 启动 Milvus 服务
default_server.start()

# 停止 Milvus 服务
default_server.stop()

Legen Sie Anwendungsvariablen fest und erhalten Sie den OpenAI-API-Schlüssel

Als nächstes legen Sie die Variablen fest und bereinigen die alten SQLite-Dateien. Wir werden SQLite zum Speichern des Chat-Verlaufs verwenden.

  • MILVUS_URI – Verbindungsinformationen zum Milvus-Server, aufgelöst nach Host und Port.

  • MILVUS_HOST – Der Host, auf dem Milvus ausgeführt wird.

  • MILVUS_PORT – Der Port, auf dem der Server lauscht.

  • DROP_EXIST – Entfernt vorhandene Milvus-Sammlungen beim Start.

  • EMBED_MODEL – sent_transformers-Modell, das zum Generieren von Einbettungsvektoren verwendet wird

  • COLLECTION_NAME – der Name der Milvus-Sammlung, die zum Speichern von Vektordaten verwendet wird

  • DIM – Abmessungen der vom Modell generierten Textvektoren

  • OPENAI_API_KEY – Schlüssel für die Large Language Model (LLM)-API

import getpass
import os

MILVUS_URI = 'http://localhost:19530'
[MILVUS_HOST, MILVUS_PORT] = MILVUS_URI.split('://')[1].split(':')
DROP_EXIST = True
EMBED_MODEL = 'all-mpnet-base-v2'
COLLECTION_NAME = 'chatbot_demo'
DIM = 768

OPENAI_API_KEY = getpass.getpass('Enter your OpenAI API key: ')

if os.path.exists('./sqlite.db'):
    os.remove('./sqlite.db')

Führen Sie den obigen Code aus, um die Variablen zu definieren und geben Sie den OpenAI-API-Schlüssel ein.

Beispielpipeline

Als nächstes müssen die Daten heruntergeladen und in Milvus gespeichert werden. Aber vorher lernen wir, wie man mit der Pipeline unstrukturierte Daten verarbeitet.

Ich werde die Homepage der offiziellen Towhee-Website als Beispiel für eine Dokumentquelle zur Demonstration verwenden. Sie können auch andere Dokument-Websites ausprobieren, um zu verstehen, wie die Pipeline verschiedene Datensätze verarbeitet.

Der folgende Code verwendet die Towhee-Pipeline:

  • Eingabe – Erstellen Sie eine neue Pipeline und übergeben Sie Quelldaten.

  • map – Verwenden Sie ops.text_loader(), um die URL zu analysieren und sie „doc“ zuzuordnen.

  • flat_map – Verwenden Sie ops.text_splitter(), um das Dokument zur späteren Speicherung in Fragmente aufzuteilen.

  • Ausgabe – Wählen Sie die gebrauchsfertige Datenausgabe aus.

Übergeben Sie diese Pipeline an die DataCollection und beobachten Sie, wie sie funktioniert.

from towhee import pipe, ops, DataCollectionpipe_load = (  

from towhee import pipe, ops, DataCollection

pipe_load = (
    pipe.input('source')
        .map('source', 'doc', ops.text_loader())
        .flat_map('doc', 'doc_chunks', ops.text_splitter(chunk_size=300))
        .output('source', 'doc_chunks')
)
DataCollection(pipe_load('https://towhee.io')).show()

Das Folgende ist die Ausgabe:

Beispiel für eine Einbettungspipeline

Sehen Sie sich als Nächstes das folgende Beispiel einer Einbettungspipeline an, um diese Dokumentblöcke in Vektoren zu konvertieren. Die Pipeline führt ops.sentence_embedding.sbert() für jeden Dokumentblock über map() aus. Im Beispiel haben wir 1 Textblock übergeben.

pipe_embed = (
    pipe.input('doc_chunk')
        .map('doc_chunk', 'vec', ops.sentence_embedding.sbert(model_name=EMBED_MODEL))
        .map('vec', 'vec', ops.np_normalize())
        .output('doc_chunk', 'vec')
)

text = '''SOTA Models

We provide 700+ pre-trained embedding models spanning 5 fields (CV, NLP, Multimodal, Audio, Medical), 15 tasks, and 140+ model architectures.
These include BERT, CLIP, ViT, SwinTransformer, data2vec, etc.
'''

DataCollection(pipe_embed(text)).show()

Führen Sie diesen Code aus, um zu sehen, wie diese Pipeline einzelne Dokumentfragmente in Vektoren umwandelt.

Milvus einrichten

Erstellen Sie eine Sammlung zum Speichern von Daten.

Im folgenden Code verwenden wir MILVUS_HOST und MILVUS_PORT, um eine Verbindung zu Milvus herzustellen, alle vorhandenen Sammlungen zu löschen und die Funktion create_collection() zu definieren, um eine neue Sammlung zu erstellen.

Das Schema der neuen Sammlung lautet wie folgt:

  • id – Bezeichner, Datentyp ist Ganzzahl.

  • Einbettung – Vektor, Datentyp Float-Vektor.

  • text – der Text des Dokumentblocks, der dem Vektor entspricht, der Datentyp ist string.

from pymilvus import (
    connections, utility, Collection,
    CollectionSchema, FieldSchema, DataType
)


def create_collection(collection_name):
    connections.connect(host=MILVUS_HOST, port=MILVUS_PORT)
    
    has_collection = utility.has_collection(collection_name)
    
    if has_collection:
        collection = Collection(collection_name)
        if DROP_EXIST:
            collection.drop()
        else:
            return collection

    # 创建 collection
    fields = [
        FieldSchema(name='id', dtype=DataType.INT64, is_primary=True, auto_id=True),
        FieldSchema(name='embedding', dtype=DataType.FLOAT_VECTOR, dim=DIM),
        FieldSchema(name='text', dtype=DataType.VARCHAR, max_length=500)
    ]
    schema = CollectionSchema(
        fields=fields,
        description="Towhee demo",
        enable_dynamic_field=True
        )
    collection = Collection(name=collection_name, schema=schema)
    
    index_params = {
        'metric_type': 'IP',
        'index_type': 'IVF_FLAT',
        'params': {'nlist': 1024}
        }
    collection.create_index(
        field_name='embedding', 
        index_params=index_params
    )
    return collection

Pipeline einfügen

Fügen Sie nun den Textvektor in Milvus ein.

Der folgende Code funktioniert:

  • Neue Sammlung erstellen

  • Neue Dokumentdaten laden

  • Schneiden Sie das neue Dokument in Stücke

  • Verwenden Sie EMBED_MODEL, um Vektoren für Textblöcke zu generieren

  • Fügen Sie den Textblockvektor und die entsprechenden Textblockdaten in Milvus ein

load_data = (
    pipe.input('collection_name', 'source')
        .map('collection_name', 'collection', create_collection)
        .map('source', 'doc', ops.text_loader())
        .flat_map('doc', 'doc_chunk', ops.text_splitter(chunk_size=300))
        .map('doc_chunk', 'vec', ops.sentence_embedding.sbert(model_name=EMBED_MODEL))
        .map('vec', 'vec', ops.np_normalize())
        .map(('collection_name', 'vec', 'doc_chunk'), 'mr',
             ops.ann_insert.osschat_milvus(host=MILVUS_HOST, port=MILVUS_PORT))
        .output('mr')
)

Mit dem folgenden Code konvertieren wir den Inhalt der Enzyklopädieseite von Frodo Beutlin in einen textschnellen Vektor und fügen ihn in Milvus ein.

project_name = 'towhee_demo'
data_source = 'https://en.wikipedia.org/wiki/Frodo_Baggins'
mr = load_data(COLLECTION_NAME, data_source)

print('Doc chunks inserted:', len(mr.to_list()))

Schließlich wurden insgesamt 408 Textblockvektoren eingefügt:

2023-07-31 16:50:53,369 - 139993906521792 - node.py-node:167 - INFO: Begin to run Node-_input2023-07-31 16:50:53,371 - 139993906521792 - node.py-node:167 - INFO: Begin to run Node-create_collection-02023-07-31 16:50:53,373 - 139993881343680 - node.py-node:167 - INFO: Begin to run Node-text-loader-12023-07-31 16:50:53,374 - 139993898129088 - node.py-node:167 - INFO: Begin to run Node-text-splitter-22023-07-31 16:50:53,376 - 139993872950976 - node.py-node:167 - INFO: Begin to run Node-sentence-embedding/sbert-32023-07-31 16:50:53,377 - 139993385268928 - node.py-node:167 - INFO: Begin to run Node-np-normalize-42023-07-31 16:50:53,378 - 139993376876224 - node.py-node:167 - INFO: Begin to run Node-ann-insert/osschat-milvus-52023-07-31 16:50:53,379 - 139993368483520 - node.py-node:167 - INFO: Begin to run Node-_output

(snip)

Categories:
2023-07-31 18:07:53,530 - 140552729257664 - logger.py-logger:14 - DETAIL: Skipping sentence because does not exceed 5 word tokens
Categories
2023-07-31 18:07:53,532 - 140552729257664 - logger.py-logger:14 - DETAIL: Skipping sentence because does not exceed 3 word tokens
Hidden categories
2023-07-31 18:07:53,533 - 140552729257664 - logger.py-logger:14 - DETAIL: Skipping sentence because does not exceed 3 word tokens
Hidden categories
2023-07-31 18:07:53,533 - 140552729257664 - logger.py-logger:14 - DETAIL: Not narrative. Text does not contain a verb:

Hidden categories: 
2023-07-31 18:07:53,534 - 140552729257664 - logger.py-logger:14 - DETAIL: Skipping sentence because does not exceed 5 word tokens
Hidden categories

Doc chunks inserted: 408

03. Durchsuchen Sie die Wissensdatenbank

Textblockvektoren wurden in Milvus gespeichert und Vektorabfragen können jetzt durchgeführt werden.

Die folgende Funktion erstellt eine Abfragepipeline. Beachten Sie, dass dies der wichtigste Schritt in diesem Tutorial ist!

ops.ann_search.osschat_milvus(host=MILVUS_HOST, port=MILVUS_PORT, 
                              **{'metric_type': 'IP', 'limit': 3, 'output_fields': ['text']}))

OSSChat_milvus ( https://towhee.io/ann-search/osschat-milvus) fragt die Milvus-Vektordatenbank nach Dokumentfragmenten ab, die mit dem Abfragetext übereinstimmen.

Das Folgende ist der gesamte Code der Abfragepipeline:

pipe_search = (
    pipe.input('collection_name', 'query')
        .map('query', 'query_vec', ops.sentence_embedding.sbert(model_name=EMBED_MODEL))
        .map('query_vec', 'query_vec', ops.np_normalize())
        .map(('collection_name', 'query_vec'), 'search_res',
             ops.ann_search.osschat_milvus(host=MILVUS_HOST, port=MILVUS_PORT,
                                           **{'metric_type': 'IP', 'limit': 3, 'output_fields': ['text']}))
        .flat_map('search_res', ('id', 'score', 'text'), lambda x: (x[0], x[1], x[2]))
        .output('query', 'text', 'score')
)

Jetzt können Sie versuchen, die folgenden Fragen abzufragen:

query = 'Who is Frodo Baggins?'
DataCollection(pipe_search(project_name, query)).show()

Es ist nicht schwer herauszufinden, dass das von uns verwendete Modell 3 übereinstimmende Ergebnisse zurückgegeben hat (Hinweis: limit=3 wurde zuvor in ann_search.osschat_milvus angegeben):

04. Großes Sprachmodell (LLM) hinzufügen

Als nächstes muss LLM zum Chatbot hinzugefügt werden. Auf diese Weise können Benutzer eine Konversation mit dem Chatbot beginnen. In diesem Beispiel verwenden wir den Modelldienst hinter OpenAI ChatGPT: GPT-3.5.

Chat-Aufzeichnung

Um LLM-Antworten genauer zu machen, müssen wir die Chat-Aufzeichnungen von Benutzern und Robotern speichern und diese Aufzeichnungen bei Abfragen aufrufen. SQLite kann zum Verwalten von Chat-Aufzeichnungen verwendet werden.

Die folgenden Funktionen werden zum Abrufen von Chat-Aufzeichnungen verwendet:

<section id="nice" data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="font-size: 16px; padding: 0 10px; line-height: 1.6; word-spacing: 0px; letter-spacing: 0px; word-break: break-word; word-wrap: break-word; text-align: left; color: #3E3E3E; font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, 'PingFang SC', Cambria, Cochin, Georgia, Times, 'Times New Roman', serif;"><pre class="custom" data-tool="mdnice编辑器" style="margin-top: 10px; margin-bottom: 10px; border-radius: 5px; box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px; text-align: left;"><span style="display: block; background: url(https://files.mdnice.com/user/3441/876cad08-0422-409d-bb5a-08afec5da8ee.svg); height: 30px; width: 100%; background-size: 40px; background-repeat: no-repeat; background-color: #282c34; margin-bottom: -7px; border-radius: 5px; background-position: 10px 10px;"></span><code class="hljs" style="overflow-x: auto; padding: 16px; color: #abb2bf; display: -webkit-box; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; font-size: 12px; -webkit-overflow-scrolling: touch; padding-top: 15px; background: #282c34; border-radius: 5px;">query = 'Who is Frodo Baggins?'
DataCollection(pipe_search(project_name, query)).show()
</code></pre>
</section>

Der folgende Funktionsbenutzer speichert den Chatverlauf:

pipe_add_history = (
    pipe.input('collection_name', 'session', 'question', 'answer')
        .map(('collection_name', 'session', 'question', 'answer'), 'history', ops.chat_message_histories.sql(method='add'))
        .output('history')
)

LLM-Abfragepipeline

Erstellen Sie eine Pipeline, um die Abfrage an LLM weiterzuleiten.

Diese LLM-Abfragepipeline kann:

  • Durchsuchen Sie die Milvus-Vektordatenbank anhand von Benutzeranfragen

  • Rufen Sie den aktuellen Chatverlauf ab und speichern Sie ihn

  • Übertragen Sie Benutzeranfragen, Milvus-Suchergebnisse und Chat-Datensätze an ChatGPT

  • Notieren Sie die Fragen und Antworten für diese Runde

  • Zurück zur endgültigen Antwort

chat = (
    pipe.input('collection_name', 'query', 'session')
        .map('query', 'query_vec', ops.sentence_embedding.sbert(model_name=EMBED_MODEL))
        .map('query_vec', 'query_vec', ops.np_normalize())
        .map(('collection_name', 'query_vec'), 'search_res',
            ops.ann_search.osschat_milvus(host=MILVUS_HOST,
                                        port=MILVUS_PORT,
                                        **{'metric_type': 'IP', 'limit': 3, 'output_fields': ['text']}))
        .map('search_res', 'knowledge', lambda y: [x[2] for x in y])
        .map(('collection_name', 'session'), 'history', ops.chat_message_histories.sql(method='get'))
        .map(('query', 'knowledge', 'history'), 'messages', ops.prompt.question_answer())
        .map('messages', 'answer', ops.LLM.OpenAI(api_key=OPENAI_API_KEY,
                                                model_name='gpt-3.5-turbo',
                                                temperature=0.8))
        .map(('collection_name', 'session', 'query', 'answer'), 'new_history', ops.chat_message_histories.sql(method='add'))
        .output('query', 'history', 'answer', )
)

Bevor wir eine Verbindung zur grafischen Benutzeroberfläche (GUI) herstellen, müssen wir die folgende Pipeline testen.

new_query = 'Where did Frodo take the ring?'
DataCollection(chat(COLLECTION_NAME, new_query, session_id)).show()

Das Folgende ist die Ausgabe und die Ergebnisse:

Glückwunsch! Diese Pipeline wurde erfolgreich gebaut! Als nächstes können Sie die Gradio-Schnittstelle erstellen!

Gradio-Schnittstelle

Zunächst sind einige Funktionen erforderlich, um über die UUID eine Sitzungs-ID zu erstellen, Benutzeranfragen auf der Schnittstelle zu akzeptieren und darauf zu antworten.

import uuidimport io

def create_session_id():
    uid = str(uuid.uuid4())
    suid = ''.join(uid.split('-'))
    return 'sess_' + suid


def respond(session, query):
    res = chat(COLLECTION_NAME, query, session).get_dict()
    answer = res['answer']
    response = res['history']
    response.append((query, answer))
    return response

Anschließend erstellt die Gradio-Schnittstelle mithilfe dieser Funktionen einen Chatbot. Die Blocks-API wird zum Erstellen von Chatbot-Schnittstellen verwendet. Die Schaltfläche „Nachricht senden“ sendet die Anfrage über die Antwortfunktion an ChatGPT.

import gradio as gr

with gr.Blocks() as demo:
    session_id = gr.State(create_session_id)

    with gr.Row():
        with gr.Column(scale=2):
            gr.Markdown('''## Chat''')
            conversation = gr.Chatbot(label='conversation').style(height=300)
            question = gr.Textbox(label='question', value=None)
    
            send_btn = gr.Button('Send Message')
            send_btn.click(
                fn=respond,
                inputs=[
                    session_id,
                    question
                ],
                outputs=conversation,
            )

demo.launch(server_name='127.0.0.1', server_port=8902)

Die Schnittstelle ist wie folgt:

An diesem Punkt ist ein intelligenter Chatbot fertiggestellt, der Vektorabruf und LLM-Generierung kombiniert!

05. Zusammenfassung

Um es noch einmal zusammenzufassen: Wir haben zunächst die Towhee-Pipeline erstellt, um unstrukturierte Daten zu verarbeiten, sie in Vektoren umzuwandeln und sie in der Milvus-Vektordatenbank zu speichern. Anschließend wurde eine Abfragepipeline erstellt und LLM mit dem Chatbot verbunden. Abschließend wird eine grundlegende Chatbot-Schnittstelle erstellt.

Kurz gesagt, Milvus ist hoch skalierbar, bietet effiziente Suchfunktionen für Vektorähnlichkeiten und kann Entwicklern dabei helfen, auf einfache Weise ML- und KI-Anwendungen wie Chat-Roboter, Empfehlungssysteme, Bild- oder Texterkennung usw. zu erstellen. Ich freue mich darauf, dass jeder Milvus nutzt, um bessere Anwendungen zu erstellen!

  • Autor dieses Artikels

Eric Goebelbecker lebt derzeit in New York und verfügt über 25 Jahre Erfahrung auf den Finanzmärkten. Er ist verantwortlich für den Aufbau der Infrastruktur für das Financial Information Exchange (FIX)-Protokollnetzwerk und Marktdatenanalysesysteme. Eric beschäftigt sich leidenschaftlich mit der Erforschung von Tools und Software, die die Teamproduktivität verbessern.


  • Wenn Sie Probleme mit der Verwendung von Milvus- oder Zilliz-Produkten haben, können Sie den WeChat-Assistenten „zilliz-tech“ hinzufügen, um der Kommunikationsgruppe beizutreten.

  • Willkommen beim öffentlichen WeChat-Konto „Zilliz“, um die neuesten Informationen zu erhalten.

200 Yuan Geldstrafe und mehr als 1 Million Yuan beschlagnahmt You Yuxi: Die Bedeutung hochwertiger chinesischer Dokumente Musks Hardcore-Migrationsserver Solon für JDK 21, virtuelle Threads sind unglaublich! ! ! TCP-Überlastungskontrolle rettet das Internet- Flutter für OpenHarmony ist da. Die LTS-Periode des Linux-Kernels wird von 6 auf 2 Jahre wiederhergestellt. Go 1.22 behebt den Variablenfehler der For-Schleife. Svelte hat ein „neues Rad“ gebaut – Runen. Google feiert sein 25-jähriges Jubiläum
{{o.name}}
{{m.name}}

Ich denke du magst

Origin my.oschina.net/u/4209276/blog/10114595
Empfohlen
Rangfolge