🚀 Essayez Zilliz Cloud, la version entièrement gérée de Milvus, gratuitement—découvrez des performances 10x plus rapides ! Essayez maintenant>>

milvus-logo
LFAI

Vue d'ensemble

  • Engineering
September 15, 2021
Zhen Chen

Vue d'ensemble

URL du projet : https://github.com/milvus-io/milvus_cli

Préparation : Python3.8, Click 8.0.x

Grouper les commandes

Créer une commande

import click
from utils import PyOrm

@click.group(no_args_is_help=False, add_help_option=False, invoke_without_command=True)
@click.pass_context
def cli(ctx):
    """Milvus CLI"""
    ctx.obj = PyOrm() # PyOrm is a util class which wraps the milvus python SDK. You can pass any class instance here. Any command function passed by @click.obj can call it.

if __name__ == '__main__':
    cli()

Comme dans le code ci-dessus, nous utilisons @click.group() pour créer un groupe de commandes cli comme point d'entrée. Pour implémenter une CLI prompte, nous devons désactiver les messages d'aide pour l'entrée, donc nous ajoutons no_args_is_help=False, add_help_option=False et invoke_without_command=True. Rien ne sera imprimé si nous saisissons cli dans le terminal uniquement.

En outre, nous utilisons @click.pass_context pour transmettre un contexte à ce groupe en vue d'une utilisation ultérieure.

Créer une sous-commande du groupe de commandes

Nous ajoutons ensuite la première sous-commande help sous cli:

# Print the help message of specified command.
def print_help_msg(command):
    with click.Context(command) as ctx:
        click.echo(command.get_help(ctx))


# Use @cli.command() to create a sub command of cli.
@cli.command()
def help():
    """Show help messages."""
    # Print help message of cli.
    click.echo(print_help_msg(cli))

Nous pouvons maintenant utiliser cli help dans le terminal :

$ python milvus_cli/scripts/milvus_cli.py help

Créer un sous-groupe d'un groupe de commandes

Non seulement nous voulons avoir une sous-commande comme cli help, mais nous avons aussi besoin de sous-groupes de commandes comme cli list collection, cli list partition et cli list indexes.

Tout d'abord, nous créons un sous-groupe de commandes list, ici nous pouvons passer le premier paramètre à @cli.group comme nom de commande au lieu d'utiliser le nom de la fonction par défaut, de sorte que nous pouvons réduire les noms de fonctions dupliqués.

Attention, nous utilisons ici @cli.group() au lieu de @click.group afin de créer un sous-groupe du groupe d'origine.

Nous utilisons ensuite @click.pass_obj pour transmettre context.obj aux sous-commandes de ce sous-groupe.

@cli.group('list', no_args_is_help=False)
@click.pass_obj
def listDetails(obj):
    """List collections, partitions and indexes."""
    pass

Ensuite, nous ajoutons des sous-commandes à ce sous-groupe par @listDetails.command() (et non @cli.command()). Ce n'est qu'un exemple, vous pouvez ignorer l'implémentation et nous en discuterons plus tard.

@listDetails.command()
@click.option('--timeout', 'timeout', help="[Optional] - An optional duration of time in seconds to allow for the RPC. When timeout is set to None, client waits until server response or error occur.", default=None)
@click.option('--show-loaded', 'showLoaded', help="[Optional] - Only show loaded collections.", default=False)
@click.pass_obj
def collections(obj, timeout, showLoaded):
    """List all collections."""
    try:
        obj.checkConnection()
        click.echo(obj.listCollections(timeout, showLoaded))
    except Exception as e:
        click.echo(message=e, err=True)


@listDetails.command()
@click.option('-c', '--collection', 'collection', help='The name of collection.', default='')
@click.pass_obj
def partitions(obj, collection):
    """List all partitions of the specified collection."""
    try:
        obj.checkConnection()
        validateParamsByCustomFunc(
            obj.getTargetCollection, 'Collection Name Error!', collection)
        click.echo(obj.listPartitions(collection))
    except Exception as e:
        click.echo(message=e, err=True)

Une fois toutes ces opérations terminées, nous avons une commande miltigroup qui ressemble à ceci :

image image

Personnaliser une commande

Ajouter des options

Vous pouvez ajouter des options à une commande qui sera utilisée comme cli --test-option value.

Voici un exemple, nous ajoutons trois options alias, host et port pour spécifier une adresse pour se connecter à Milvus.

Les deux premiers paramètres définissent le nom court et le nom complet de l'option, le troisième paramètre définit le nom de la variable, le paramètre help spécifie le message d'aide court, le paramètre default spécifie la valeur par défaut et le paramètre type spécifie le type de valeur.

Toutes les valeurs des options seront transmises à la fonction dans l'ordre de leur définition.

@cli.command(no_args_is_help=False)
@click.option('-a', '--alias', 'alias', help="Milvus link alias name, default is `default`.", default='default', type=str)
@click.option('-h', '--host', 'host', help="Host name, default is `127.0.0.1`.", default='127.0.0.1', type=str)
@click.option('-p', '--port', 'port', help="Port, default is `19530`.", default=19530, type=int)
@click.pass_obj
def connect(obj, alias, host, port):
    pass

Ajouter des options de drapeau

Nous avons utilisé les options ci-dessus pour transmettre une valeur, mais il arrive que nous ayons simplement besoin d'un drapeau comme valeur booléenne.

Dans l'exemple ci-dessous, l'option autoId est une option de drapeau et ne transmet aucune donnée à la fonction, nous pouvons donc l'utiliser comme cli create collection -c c_name -p p_name -a.

@createDetails.command('collection')
@click.option('-c', '--collection-name', 'collectionName', help='Collection name to be created.', default='')
@click.option('-p', '--schema-primary-field', 'primaryField', help='Primary field name.', default='')
@click.option('-a', '--schema-auto-id', 'autoId', help='Enable auto id.', default=False, is_flag=True)
@click.pass_obj
def createCollection(obj, collectionName, primaryField, autoId, description, fields):
    pass

Ajouter des arguments

Dans ce projet, nous remplaçons tous les arguments par des options. Mais nous introduisons toujours l'utilisation des arguments ici. Contrairement aux options, les arguments sont utilisés comme cli COMMAND [OPTIONS] ARGUEMENTS. Si nous convertissons l'exemple ci-dessus en utilisation d'arguments, ce sera comme ceci :

@createDetails.command('collection')
@click.argument('collectionName')
@click.option('-p', '--schema-primary-field', 'primaryField', help='Primary field name.', default='')
@click.option('-a', '--schema-auto-id', 'autoId', help='Enable auto id.', default=False, is_flag=True)
@click.pass_obj
def createCollection(obj, collectionName, primaryField, autoId, description, fields):
    pass

L'utilisation devrait alors être cli create collection c_name -p p_name -a.

Ajouter un message d'aide complet

Comme nous avons défini le message d'aide court ci-dessus, nous pouvons définir le message d'aide complet dans la fonction :

@cli.command(no_args_is_help=False)
@click.option('-a', '--alias', 'alias', help="Milvus link alias name, default is `default`.", default='default', type=str)
@click.option('-h', '--host', 'host', help="Host name, default is `127.0.0.1`.", default='127.0.0.1', type=str)
@click.option('-p', '--port', 'port', help="Port, default is `19530`.", default=19530, type=int)
@click.pass_obj
def connect(obj, alias, host, port):
    """
    Connect to Milvus.

    Example:

        milvus_cli > connect -h 127.0.0.1 -p 19530 -a default
    """
    try:
        obj.connect(alias, host, port)
    except Exception as e:
        click.echo(message=e, err=True)
    else:
        click.echo("Connect Milvus successfully!")
        click.echo(obj.showConnection(alias))

Le premier bloc à l'intérieur de la fonction est le message d'aide qui sera imprimé après la saisie de cli connect --help.

milvus_cli > connect --help
Usage: milvus_cli.py connect [OPTIONS]

  Connect to Milvus.

  Example:

      milvus_cli > connect -h 127.0.0.1 -p 19530 -a default

Options:
  -a, --alias TEXT    Milvus link alias name, default is `default`.
  -h, --host TEXT     Host name, default is `127.0.0.1`.
  -p, --port INTEGER  Port, default is `19530`.
  --help              Show this message and exit.

Ajouter une confirmation

Il arrive que l'utilisateur doive confirmer une action, en particulier la suppression d'un élément. Nous pouvons ajouter click.confirm pour faire une pause et demander à l'utilisateur de confirmer :

@deleteSth.command('collection')
@click.option('-c', '--collection', 'collectionName', help='The name of collection to be deleted.', default='')
@click.option('-t', '--timeout', 'timeout', help='An optional duration of time in seconds to allow for the RPC. If timeout is set to None, the client keeps waiting until the server responds or an error occurs.', default=None, type=int)
@click.pass_obj
def deleteCollection(obj, collectionName, timeout):
    """
    Drops the collection together with its index files.

    Example:

        milvus_cli > delete collection -c car
    """
    click.echo(
        "Warning!\nYou are trying to delete the collection with data. This action cannot be undone!\n")
    if not click.confirm('Do you want to continue?'):
        return
    pass

Comme dans l'exemple ci-dessus, une conversation de confirmation s'affichera sous la forme suivante : Aborted!ant to continue? [y/N]:.

Ajouter des invites

Pour mettre en place des invites, il suffit d'ajouter click.prompt.

@cli.command()
@click.pass_obj
def query(obj):
    """
    Query with a set of criteria, and results in a list of records that match the query exactly.
    """
    collectionName = click.prompt(
        'Collection name', type=click.Choice(obj._list_collection_names()))
    expr = click.prompt('The query expression(field_name in [x,y])')
    partitionNames = click.prompt(
        f'The names of partitions to search(split by "," if multiple) {obj._list_partition_names(collectionName)}', default='')
    outputFields = click.prompt(
        f'Fields to return(split by "," if multiple) {obj._list_field_names(collectionName)}', default='')
    timeout = click.prompt('timeout', default='')
    pass

L'invite s'affichera à chaque fois que click.prompt sera utilisé. Nous utilisons quelques invites en série pour que cela ressemble à une conversation continue. Cela permet de s'assurer que l'utilisateur saisira les données dans l'ordre souhaité. Dans ce cas, l'utilisateur doit d'abord choisir une collection, puis récupérer toutes les partitions de cette collection, avant de les montrer à l'utilisateur pour qu'il les choisisse.

Ajouter des choix

Parfois, vous souhaitez que l'utilisateur ne saisisse qu'une plage/un type de valeur limité, vous pouvez ajouter type=click.Choice([<any>]) à click.prompt, click.options, etc...

Par exemple,

collectionName = click.prompt(
        'Collection name', type=click.Choice(['collection_1', 'collection_2']))

L'utilisateur ne peut alors saisir que collection_1 ou collection_2, une erreur se produira si d'autres valeurs sont saisies.

Ajouter un écran clair

Vous pouvez utiliser click.clear() pour l'implémenter.

@cli.command()
def clear():
    """Clear screen."""
    click.clear()

Conseils supplémentaires

  • La valeur par défaut est None, il est donc inutile de spécifier la valeur par défaut None. De plus, la valeur par défaut None entraînera l'affichage continu de click.prompt si vous souhaitez laisser une valeur vide pour passer par-dessus.

Mise en œuvre d'une invite CLI pour la saisie par l'utilisateur

Pourquoi l'invite CLI ?

Pour le fonctionnement de la base de données, nous avons besoin d'une connexion continue à une instance. Si nous utilisons le mode de ligne de commande d'origine, la connexion sera interrompue après chaque commande exécutée. Nous voulons également stocker certaines données lors de l'utilisation du CLI, et les nettoyer après la sortie.

Mise en œuvre

  1. Utilisez while True pour écouter continuellement les entrées de l'utilisateur.
def runCliPrompt():
    while True:
        astr = input('milvus_cli > ')
        try:
            cli(astr.split())
        except SystemExit:
            # trap argparse error message
            # print('error', SystemExit)
            continue


if __name__ == '__main__':
    runCliPrompt()
  1. L'utilisation de input uniquement entraînera la conversion automatique des touches fléchées up, down, left, right, de la touche tab et d'autres touches en chaînes Acsii. En outre, les commandes de l'historique ne peuvent pas être lues à partir de la session. Nous ajoutons donc readline à la fonction runCliPrompt.
def runCliPrompt():
    while True:
            import readline
        readline.set_completer_delims(' \t\n;')
        astr = input('milvus_cli > ')
        try:
            cli(astr.split())
        except SystemExit:
            # trap argparse error message
            # print('error', SystemExit)
            continue
  1. Ajouter quit CLI.
@cli.command('exit')
def quitapp():
    """Exit the CLI."""
    global quitapp
    quitapp = True


quitapp = False  # global flag


def runCliPrompt():
    while not quitapp:
            import readline
        readline.set_completer_delims(' \t\n;')
        astr = input('milvus_cli > ')
        try:
            cli(astr.split())
        except SystemExit:
            # trap argparse error message
            # print('error', SystemExit)
            continue
  1. Correction de l'erreur KeyboardInterrupt lors de l'utilisation de ctrl C pour quitter.
def runCliPrompt():
    try:
        while not quitapp:
            import readline
            readline.set_completer_delims(' \t\n;')
            astr = input('milvus_cli > ')
            try:
                cli(astr.split())
            except SystemExit:
                # trap argparse error message
                # print('error', SystemExit)
                continue
    except KeyboardInterrupt:
        sys.exit(0)
  1. Après tous ces réglages, le CLI ressemble maintenant à ce qui suit :
milvus_cli >
milvus_cli > connect
+-------+-----------+
| Host  | 127.0.0.1 |
| Port  |   19530   |
| Alias |  default  |
+-------+-----------+

milvus_cli > help
Usage:  [OPTIONS] COMMAND [ARGS]...

  Milvus CLI

Commands:
  clear     Clear screen.
  connect   Connect to Milvus.
  create    Create collection, partition and index.
  delete    Delete specified collection, partition and index.
  describe  Describe collection or partition.
  exit      Exit the CLI.
  help      Show help messages.
  import    Import data from csv file with headers and insert into target...
  list      List collections, partitions and indexes.
  load      Load specified collection.
  query     Query with a set of criteria, and results in a list of...
  release   Release specified collection.
  search    Conducts a vector similarity search with an optional boolean...
  show      Show connection, loading_progress and index_progress.
  version   Get Milvus CLI version.

milvus_cli > exit

Implémentation manuelle de l'autocomplétion

Contrairement à l'autocomplétion du shell de click, notre projet reprend la ligne de commande et utilise une boucle pour récupérer les données de l'utilisateur afin d'implémenter une ligne de commande rapide. Nous devons donc lier un compléteur à readline.

class Completer(object):
    RE_SPACE = re.compile('.*\s+$', re.M)
    CMDS_DICT = {
        'clear': [],
        'connect': [],
        'create': ['collection', 'partition', 'index'],
        'delete': ['collection', 'partition', 'index'],
        'describe': ['collection', 'partition'],
        'exit': [],
        'help': [],
        'import': [],
        'list': ['collections', 'partitions', 'indexes'],
        'load': [],
        'query': [],
        'release': [],
        'search': [],
        'show': ['connection', 'index_progress', 'loading_progress'],
        'version': [],
    }

    def __init__(self) -> None:
        super().__init__()
        self.COMMANDS = list(self.CMDS_DICT.keys())
        self.createCompleteFuncs(self.CMDS_DICT)

    def createCompleteFuncs(self, cmdDict):
        for cmd in cmdDict:
            sub_cmds = cmdDict[cmd]
            complete_example = self.makeComplete(cmd, sub_cmds)
            setattr(self, 'complete_%s' % cmd, complete_example)

    def makeComplete(self, cmd, sub_cmds):
        def f_complete(args):
            f"Completions for the {cmd} command."
            if not args:
                return self._complete_path('.')
            if len(args) <= 1 and not cmd == 'import':
                return self._complete_2nd_level(sub_cmds, args[-1])
            return self._complete_path(args[-1])
        return f_complete

    def _listdir(self, root):
        "List directory 'root' appending the path separator to subdirs."
        res = []
        for name in os.listdir(root):
            path = os.path.join(root, name)
            if os.path.isdir(path):
                name += os.sep
            res.append(name)
        return res

    def _complete_path(self, path=None):
        "Perform completion of filesystem path."
        if not path:
            return self._listdir('.')
        dirname, rest = os.path.split(path)
        tmp = dirname if dirname else '.'
        res = [os.path.join(dirname, p)
               for p in self._listdir(tmp) if p.startswith(rest)]
        # more than one match, or single match which does not exist (typo)
        if len(res) > 1 or not os.path.exists(path):
            return res
        # resolved to a single directory, so return list of files below it
        if os.path.isdir(path):
            return [os.path.join(path, p) for p in self._listdir(path)]
        # exact file match terminates this completion
        return [path + ' ']

    def _complete_2nd_level(self, SUB_COMMANDS=[], cmd=None):
        if not cmd:
            return [c + ' ' for c in SUB_COMMANDS]
        res = [c for c in SUB_COMMANDS if c.startswith(cmd)]
        if len(res) > 1 or not (cmd in SUB_COMMANDS):
            return res
        return [cmd + ' ']

    def complete(self, text, state):
        "Generic readline completion entry point."
        buffer = readline.get_line_buffer()
        line = readline.get_line_buffer().split()
        # show all commands
        if not line:
            return [c + ' ' for c in self.COMMANDS][state]
        # account for last argument ending in a space
        if self.RE_SPACE.match(buffer):
            line.append('')
        # resolve command to the implementation function
        cmd = line[0].strip()
        if cmd in self.COMMANDS:
            impl = getattr(self, 'complete_%s' % cmd)
            args = line[1:]
            if args:
                return (impl(args) + [None])[state]
            return [cmd + ' '][state]
        results = [
            c + ' ' for c in self.COMMANDS if c.startswith(cmd)] + [None]
        return results[state]

Après avoir défini Completer, nous pouvons le lier à readline :

comp = Completer()


def runCliPrompt():
    try:
        while not quitapp:
            import readline
            readline.set_completer_delims(' \t\n;')
            readline.parse_and_bind("tab: complete")
            readline.set_completer(comp.complete)
            astr = input('milvus_cli > ')
            try:
                cli(astr.split())
            except SystemExit:
                # trap argparse error message
                # print('error', SystemExit)
                continue
    except KeyboardInterrupt:
        sys.exit(0)

Ajouter une option unique

Pour la ligne de commande rapide, parfois nous ne voulons pas exécuter complètement les scripts pour obtenir certaines informations telles que la version. Un bon exemple est Python, lorsque vous tapez python dans le terminal, la ligne de commande promtp s'affichera, mais elle ne renverra qu'un message de version et n'entrera pas dans les scripts d'invite si vous tapez python -V. Nous pouvons donc utiliser sys.args dans notre code pour l'implémenter.

def runCliPrompt():
    args = sys.argv
    if args and (args[-1] == '--version'):
        print(f"Milvus Cli v{getPackageVersion()}")
        return
    try:
        while not quitapp:
            import readline
            readline.set_completer_delims(' \t\n;')
            readline.parse_and_bind("tab: complete")
            readline.set_completer(comp.complete)
            astr = input('milvus_cli > ')
            try:
                cli(astr.split())
            except SystemExit:
                # trap argparse error message
                # print('error', SystemExit)
                continue
    except KeyboardInterrupt:
        sys.exit(0)


if __name__ == '__main__':
    runCliPrompt()

Nous obtenons sys.args avant la boucle lors de la première exécution des scripts CLI. Si le dernier argument est --version, le code renverra la version du paquet sans entrer dans la boucle.

Cela sera utile une fois que nous aurons créé les codes en tant que paquet. L'utilisateur peut taper milvus_cli pour accéder à un prompt CLI, ou taper milvus_cli --version pour obtenir uniquement la version.

Construction et publication

Enfin, nous voulons créer un paquet et le publier par PYPI. Ainsi, l'utilisateur peut simplement utiliser pip install <package name> pour l'installer.

Installer localement pour tester

Avant de publier le paquetage sur PYPI, vous pouvez l'installer localement pour effectuer des tests.

Dans ce cas, vous pouvez simplement placer cd dans le répertoire du paquet et lancer pip install -e . (n'oubliez pas .).

Créer les fichiers du paquet

Voir : https://packaging.python.org/tutorials/packaging-projects/

La structure d'un paquetage doit ressembler à ce qui suit :

package_example/
├── LICENSE
├── README.md
├── setup.py
├── src/
│   ├── __init__.py
│   ├── main.py
│   └── scripts/
│       ├── __init__.py
│       └── example.py
└── tests/

Créer le répertoire du paquet

Créez le répertoire Milvus_cli avec la structure ci-dessous :

Milvus_cli/
├── LICENSE
├── README.md
├── setup.py
├── milvus_cli/
│   ├── __init__.py
│   ├── main.py
│   ├── utils.py
│   └── scripts/
│       ├── __init__.py
│       └── milvus_cli.py
└── dist/

Écrire le code d'entrée

L'entrée du script doit être dans Milvus_cli/milvus_cli/scripts, et le Milvus_cli/milvus_cli/scripts/milvus_cli.py doit être comme :

import sys
import os
import click
from utils import PyOrm, Completer


pass_context = click.make_pass_decorator(PyOrm, ensure=True)


@click.group(no_args_is_help=False, add_help_option=False, invoke_without_command=True)
@click.pass_context
def cli(ctx):
    """Milvus CLI"""
    ctx.obj = PyOrm()

"""
...
Here your code.
...
"""

@cli.command('exit')
def quitapp():
    """Exit the CLI."""
    global quitapp
    quitapp = True


quitapp = False  # global flag
comp = Completer()


def runCliPrompt():
    args = sys.argv
    if args and (args[-1] == '--version'):
        print(f"Milvus Cli v{getPackageVersion()}")
        return
    try:
        while not quitapp:
            import readline
            readline.set_completer_delims(' \t\n;')
            readline.parse_and_bind("tab: complete")
            readline.set_completer(comp.complete)
            astr = input('milvus_cli > ')
            try:
                cli(astr.split())
            except SystemExit:
                # trap argparse error message
                # print('error', SystemExit)
                continue
            except Exception as e:
                click.echo(
                    message=f"Error occurred!\n{str(e)}", err=True)
    except KeyboardInterrupt:
        sys.exit(0)


if __name__ == '__main__':
    runCliPrompt()

Modifier le code d'entrée setup.py

from setuptools import setup, find_packages

with open("README.md", "r", encoding="utf-8") as fh:
    long_description = fh.read()

setup(
    name='milvus_cli',
    version='0.1.6',
    author='Milvus Team',
    author_email='milvus-team@zilliz.com',
    url='https://github.com/milvus-io/milvus_cli',
    description='CLI for Milvus',
    long_description=long_description,
    long_description_content_type='text/markdown',
    license='Apache-2.0',
    packages=find_packages(),
    include_package_data=True,
    install_requires=[
        'Click==8.0.1',
        'pymilvus==2.0.0rc5',
        'tabulate==0.8.9'
    ],
    entry_points={
        'console_scripts': [
            'milvus_cli = milvus_cli.scripts.milvus_cli:runCliPrompt',
        ],
    },
    python_requires='>=3.8'
)

Quelques conseils ici :

  1. Nous utilisons le contenu de README.md comme description longue du paquet.
  2. Ajoutez toutes les dépendances à install_requires.
  3. Spécifiez le entry_points. Dans ce cas, nous définissons milvus_cli comme un enfant de console_scripts, de sorte que nous puissions taper milvus_cli comme commande directement après l'installation de ce paquet. Le point d'entrée de milvus_cli est la fonction runCliPrompt dans milvus_cli/scripts/milvus_cli.py.

Construction

  1. Mettez à jour le paquet build: python3 -m pip install --upgrade build

  2. Exécutez la commande build : python -m build --sdist --wheel --outdir dist/ .

  3. Deux fichiers seront générés dans le répertoire dist/:

dist/
  example_package_YOUR_USERNAME_HERE-0.0.1-py3-none-any.whl
  example_package_YOUR_USERNAME_HERE-0.0.1.tar.gz

Publier la version

Se référer à : https://packaging.python.org/tutorials/packaging-projects/#uploading-the-distribution-archives

  1. Mettre à jour le paquet twine: python3 -m pip install --upgrade twine
  2. Télécharger sur PYPI test env : python3 -m twine upload --repository testpypi dist/*
  3. Télécharger sur PYPI: python3 -m twine upload dist/*

Flux de travail CI/CD par Github

Se référer à : https://packaging.python.org/guides/publishing-package-distribution-releases-using-github-actions-ci-cd-workflows/

Nous voulons un moyen d'uploader les assets automatiquement, il peut construire les paquets et les uploader vers les releases github et PYPI.

(Pour une raison ou une autre, nous voulons que le workflow ne publie que la version pour tester PYPI).

# This is a basic workflow to help you get started with Actions

name: Update the release's assets after it published

# Controls when the workflow will run
on:
  release:
    # The workflow will run after release published
    types: [published]

# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
  # This workflow contains a single job called "build"
  build:
    # The type of runner that the job will run on
    runs-on: ubuntu-latest

    # Steps represent a sequence of tasks that will be executed as part of the job
    steps:
      # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
      - uses: actions/checkout@v2
      - uses: actions/setup-python@v2
        with:
          python-version: '3.8'
          architecture: 'x64'
      - name: Install pypa/build
        run: >-
          python -m
          pip install
          build
          --user
      - name: Clean dist/
        run: |
          sudo rm -fr dist/*
      - name: Build a binary wheel and a source tarball
        run: >-
          python -m
          build
          --sdist
          --wheel
          --outdir dist/
          .
      # Update target github release's assets
      - name: Update assets
        uses: softprops/action-gh-release@v1
        if: startsWith(github.ref, 'refs/tags/')
        with:
          files: ./dist/*
      - name: Publish distribution 📦 to Test PyPI
        if: contains(github.ref, 'beta') && startsWith(github.ref, 'refs/tags')
        uses: pypa/gh-action-pypi-publish@release/v1
        with:
          user: __token__
          password: ${{ secrets.TEST_PYPI_API_TOKEN }}
          repository_url: https://test.pypi.org/legacy/
          packages_dir: dist/
          verify_metadata: false

En savoir plus sur Milvus

Milvus est un outil puissant capable d'alimenter une vaste gamme d'applications d'intelligence artificielle et de recherche de similarités vectorielles. Pour en savoir plus sur le projet, consultez les ressources suivantes :

  • Lisez notre blog.
  • Interagissez avec notre communauté open-source sur Slack.
  • Utilisez ou contribuez à la base de données vectorielles la plus populaire au monde sur GitHub.
  • Testez et déployez rapidement des applications d'IA grâce à notre nouveau bootcamp.

Like the article? Spread the word

Continuer à Lire