Skip to content

Commit 986c472

Browse files
authored
Merge pull request #30 from dayyass/add_pip
add pip install
2 parents d8fda93 + a84053e commit 986c472

35 files changed

+119
-56
lines changed

.coveragerc

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[run]
22
branch = True
3-
source = muse_as_service
3+
source = src
44

55
[report]
66
exclude_lines =
@@ -11,9 +11,9 @@ exclude_lines =
1111
if __name__ == .__main__.:
1212

1313
omit =
14-
muse_as_service/utils.py
15-
muse_as_service/database/add_user.py
16-
muse_as_service/database/remove_user.py
14+
src/muse_as_service/utils.py
15+
src/muse_as_service/database/add_user.py
16+
src/muse_as_service/database/remove_user.py
1717

1818
show_missing = True
1919
ignore_errors = False

.dockerignore

+3
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,11 @@
1313

1414
venv
1515
.idea
16+
dist
1617
.git
1718

19+
src/muse_as_service.egg-info/
20+
1821
models/*
1922
!models/README.md
2023
!models/download_muse.py

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313

1414
venv
1515
.idea
16+
dist
17+
18+
src/muse_as_service.egg-info/
1619

1720
models/*
1821
!models/README.md

README.md

+15-5
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
11
[![tests](https://github.com/dayyass/muse_as_service/actions/workflows/tests.yml/badge.svg)](https://github.com/dayyass/muse_as_service/actions/workflows/tests.yml)
22
[![linter](https://github.com/dayyass/muse_as_service/actions/workflows/linter.yml/badge.svg)](https://github.com/dayyass/muse_as_service/actions/workflows/linter.yml)
33
[![codecov](https://codecov.io/gh/dayyass/muse_as_service/branch/main/graph/badge.svg?token=RRSTQY2R2Y)](https://codecov.io/gh/dayyass/muse_as_service)
4+
45
[![python 3.7](https://img.shields.io/badge/python-3.7-blue.svg)](https://github.com/dayyass/muse_as_service#requirements)
5-
[![license](https://img.shields.io/github/license/dayyass/muse_as_service)](https://github.com/dayyass/muse_as_service/blob/main/LICENSE)
66
[![release (latest by date)](https://img.shields.io/github/v/release/dayyass/muse_as_service)](https://github.com/dayyass/muse_as_service/releases/latest)
7-
[![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white)](https://github.com/dayyass/muse_as_service/blob/main/.pre-commit-config.yaml)
7+
[![license](https://img.shields.io/github/license/dayyass/muse_as_service?color=blue)](https://github.com/dayyass/muse_as_service/blob/main/LICENSE)
8+
9+
[![pre-commit](https://img.shields.io/badge/pre--commit-enabled-black)](https://github.com/dayyass/muse_as_service/blob/main/.pre-commit-config.yaml)
810
[![code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
911

12+
[![pypi version](https://img.shields.io/pypi/v/muse-as-service)](https://pypi.org/project/muse-as-service/1.1.0/)
13+
[![pypi downloads](https://img.shields.io/pypi/dm/muse-as-service)](https://pypi.org/project/muse-as-service/1.1.0/)
14+
1015
### What is MUSE?
1116
**MUSE** stands for Multilingual Universal Sentence Encoder - multilingual extension (supports [16 languages](https://github.com/dayyass/muse_as_service#muse-supported-languages)) of Universal Sentence Encoder (USE).<br>
1217
MUSE model encodes sentences into embedding vectors of fixed size.
@@ -86,21 +91,21 @@ MUSE as Service supports **GPU** inference. To launch the service with GPU suppo
8691
### Usage
8792
Since the service is usually running on server, it is important to restrict access to the service.
8893

89-
For this reason, MUSE as Service uses **token-based authorization** with [JWT](https://jwt.io) for users in sqlite database [app.db](https://github.com/dayyass/muse_as_service/tree/main/muse_as_service/database/app.db).
94+
For this reason, MUSE as Service uses **token-based authorization** with [JWT](https://jwt.io) for users in sqlite database [app.db](https://github.com/dayyass/muse_as_service/tree/main/src/muse_as_service/database/app.db).
9095

9196
Initially database has only one user with:
9297
- **username**: "admin"
9398
- **password**: "admin"
9499

95100
To add new user with `username` and `password` run:
96101
```shell script
97-
python muse_as_service/database/add_user.py --username {username} --password {password}
102+
python src/muse_as_service/database/add_user.py --username {username} --password {password}
98103
```
99104
**NOTE**: no passwords are stored in the database, only their hashes.
100105

101106
To remove the user with `username` run:
102107
```shell script
103-
python muse_as_service/database/remove_user.py --username {username}
108+
python src/muse_as_service/database/remove_user.py --username {username}
104109
```
105110

106111
MUSE as Service has the following endpoints:
@@ -164,6 +169,11 @@ print(embedding.shape) # (2, 512)
164169

165170
However it is better to use built-in client **MUSEClient** for sentence tokenization and embedding, that wraps the functionality of the python **requests** package and provides user with a simpler interface.
166171

172+
To install the built-in client run:<br>
173+
`
174+
pip install muse-as-service
175+
`
176+
167177
Instead of using endpoints, listed above, directly, **MUSEClient** provides the following methods to work with:
168178
<pre>
169179
- login - method to login with `username` and `password`

app.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
from muse_as_service.app import app
2-
from muse_as_service.utils import get_argparse
1+
from src.muse_as_service.app import app
2+
from src.muse_as_service.utils import get_argparse
33

44
if __name__ == "__main__":
55

codecov.yml

+4-4
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,16 @@ codecov:
22
require_ci_to_pass: yes
33

44
ignore:
5-
- "muse_as_service/utils.py"
6-
- "muse_as_service/database/add_user.py"
7-
- "muse_as_service/database/remove_user.py"
5+
- "src/muse_as_service/utils.py"
6+
- "src/muse_as_service/database/add_user.py"
7+
- "src/muse_as_service/database/remove_user.py"
88

99
coverage:
1010
status:
1111
project:
1212
default: false
1313
source:
1414
paths:
15-
- "muse_as_service/"
15+
- "src/"
1616
target: 90%
1717
patch: off

examples/usage_client.py

+1-5
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
1-
import sys
2-
3-
sys.path.append("../muse_as_service")
4-
5-
from muse_as_service import MUSEClient # noqa: E402
1+
from muse_as_service import MUSEClient
62

73
# params
84
ip = "localhost"

muse_as_service/__init__.py

-4
This file was deleted.

muse_as_service/client/__init__.py

Whitespace-only changes.

muse_as_service/database/__init__.py

Whitespace-only changes.

muse_as_service/tokenizer/__init__.py

Whitespace-only changes.

pyproject.toml

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[build-system]
2+
requires = [
3+
"setuptools>=42",
4+
"wheel"
5+
]
6+
build-backend = "setuptools.build_meta"

setup.cfg

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
[metadata]
2+
name = muse-as-service
3+
version = 1.1.0
4+
author = Dani El-Ayyass
5+
author_email = dayyass@yandex.ru
6+
description = REST API for sentence tokenization and embedding using Multilingual Universal Sentence Encoder
7+
long_description = file: README.md
8+
long_description_content_type = text/markdown
9+
url = https://github.com/dayyass/muse_as_service
10+
project_urls =
11+
Bug Tracker = https://github.com/dayyass/muse_as_service/issues
12+
classifiers =
13+
Programming Language :: Python :: 3
14+
License :: OSI Approved :: MIT License
15+
Operating System :: OS Independent
16+
17+
[options]
18+
package_dir =
19+
= src
20+
packages = find:
21+
python_requires = >=3.7
22+
23+
[options.packages.find]
24+
where = src
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
### MUSE as Service
22
This module contains:
3-
- REST API [endpoints](https://github.com/dayyass/muse_as_service/blob/main/muse_as_service/endpoints.py) for MUSE embedder and tokenizer
4-
- REST API [endpoints](https://github.com/dayyass/muse_as_service/blob/main/muse_as_service/auth.py) for authorization
5-
- SQLite [database](https://github.com/dayyass/muse_as_service/blob/main/muse_as_service/database)
6-
- Flask [app](https://github.com/dayyass/muse_as_service/blob/main/muse_as_service/app.py)
7-
- MUSE [client](https://github.com/dayyass/muse_as_service/blob/main/muse_as_service/client)
3+
- REST API [endpoints](https://github.com/dayyass/muse_as_service/blob/main/src/muse_as_service/endpoints.py) for MUSE embedder and tokenizer
4+
- REST API [endpoints](https://github.com/dayyass/muse_as_service/blob/main/src/muse_as_service/auth.py) for authorization
5+
- SQLite [database](https://github.com/dayyass/muse_as_service/blob/main/src/muse_as_service/database)
6+
- Flask [app](https://github.com/dayyass/muse_as_service/blob/main/src/muse_as_service/app.py)
7+
- MUSE [client](https://github.com/dayyass/muse_as_service/blob/main/src/muse_as_service/client)

src/muse_as_service/__init__.py

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
from .client import MUSEClient
2+
3+
__version__ = "1.1.0"
4+
__all__ = ["MUSEClient"]

muse_as_service/app.py src/muse_as_service/app.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414
jwt: JWTManager = JWTManager(app)
1515

1616

17-
from muse_as_service.auth import TokenRefresh, UserLogin, UserLogout # noqa: E402
18-
from muse_as_service.endpoints import Embedder, Tokenizer # noqa: E402
17+
from .auth import TokenRefresh, UserLogin, UserLogout # noqa: E402
18+
from .endpoints import Embedder, Tokenizer # noqa: E402
1919

2020
# auth
2121
api.add_resource(UserLogin, "/login")

muse_as_service/auth.py src/muse_as_service/auth.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
)
1111
from flask_restful import Resource, reqparse
1212

13-
from muse_as_service.database.database import UserModel
13+
from .database import UserModel
1414

1515

1616
def unauthorized() -> Response:

muse_as_service/client/README.md src/muse_as_service/client/README.md

+5
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,11 @@ print(embedding.shape) # (2, 512)
6060

6161
However it is better to use built-in client **MUSEClient** for sentence tokenization and embedding, that wraps the functionality of the python **requests** package and provides user with a simpler interface.
6262

63+
To install the built-in client run:<br>
64+
`
65+
pip install muse-as-service
66+
`
67+
6368
Instead of using endpoints, listed above, directly, **MUSEClient** provides the following methods to work with:
6469
<pre>
6570
- login - method to login with `username` and `password`
+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from .client import MUSEClient
2+
3+
__all__ = ["MUSEClient"]
File renamed without changes.
File renamed without changes.
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
11
### Database
22
Since the service is usually running on the server, it is important to restrict access to the service.
33

4-
For this reason, MUSE as Service uses **token-based authorization** with [JWT](https://jwt.io) for users in sqlite database [app.db](https://github.com/dayyass/muse_as_service/tree/main/muse_as_service/database/app.db).
4+
For this reason, MUSE as Service uses **token-based authorization** with [JWT](https://jwt.io) for users in sqlite database [app.db](https://github.com/dayyass/muse_as_service/tree/main/src/muse_as_service/database/app.db).
55

66
Initially database has only one user with:
77
- **username**: "admin"
88
- **password**: "admin"
99

1010
To add new user with `username` and `password` run:
1111
```
12-
python muse_as_service/database/add_user.py --username {username} --password {password}
12+
python src.muse_as_service/database/add_user.py --username {username} --password {password}
1313
```
1414
**NOTE**: run it from parent directory `muse_as_service`
1515

1616
**NOTE**: no passwords are stored in the database, only their hashes.
1717

1818
To remove the user with `username` run:
1919
```
20-
python muse_as_service/database/remove_user.py --username {username}
20+
python src.muse_as_service/database/remove_user.py --username {username}
2121
```
2222
**NOTE**: run it from parent directory `muse_as_service`
+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from .database import UserModel
2+
3+
__all__ = ["UserModel"]

muse_as_service/database/add_user.py src/muse_as_service/database/add_user.py

+15-5
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,20 @@
11
import sqlite3
2-
import sys
32
from argparse import ArgumentParser
43
from contextlib import closing
54

6-
sys.path.append(".")
7-
from database import UserModel # noqa: E402
5+
from passlib.hash import pbkdf2_sha256 as sha256
6+
7+
8+
def generate_hash(password: str) -> str:
9+
"""
10+
Generate hash for password.
11+
12+
:param str password: password.
13+
:return: hash.
14+
:rtype: str
15+
"""
16+
17+
return sha256.hash(password)
818

919

1020
def get_argparse() -> ArgumentParser:
@@ -30,10 +40,10 @@ def get_argparse() -> ArgumentParser:
3040
parser = get_argparse()
3141
args = parser.parse_args()
3242

33-
insert_query = f'INSERT INTO users (username, password) VALUES ("{args.username}", "{UserModel.generate_hash(args.password)}");'
43+
insert_query = f'INSERT INTO users (username, password) VALUES ("{args.username}", "{generate_hash(args.password)}");'
3444

3545
# sqlite
36-
with closing(sqlite3.connect("muse_as_service/database/app.db")) as conn:
46+
with closing(sqlite3.connect("src/muse_as_service/database/app.db")) as conn:
3747
with closing(conn.cursor()) as cursor:
3848
cursor.execute(insert_query)
3949
conn.commit()
File renamed without changes.

muse_as_service/database/database.py src/muse_as_service/database/database.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
from passlib.hash import pbkdf2_sha256 as sha256
44

5-
from muse_as_service.app import db
5+
from ...muse_as_service.app import db
66

77

88
class UserModel(db.Model):

muse_as_service/database/remove_user.py src/muse_as_service/database/remove_user.py

+1-4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
import sqlite3
2-
import sys
32
from argparse import ArgumentParser
43
from contextlib import closing
54

6-
sys.path.append(".")
7-
85

96
def get_argparse() -> ArgumentParser:
107
"""
@@ -29,7 +26,7 @@ def get_argparse() -> ArgumentParser:
2926
delete_query = f"DELETE FROM users WHERE username = '{args.username}';"
3027

3128
# sqlite
32-
with closing(sqlite3.connect("muse_as_service/database/app.db")) as conn:
29+
with closing(sqlite3.connect("src/muse_as_service/database/app.db")) as conn:
3330
with closing(conn.cursor()) as cursor:
3431
cursor.execute(delete_query)
3532
conn.commit()

muse_as_service/endpoints.py src/muse_as_service/endpoints.py

+1-5
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,7 @@
33
from flask_jwt_extended import jwt_required
44
from flask_restful import Resource, reqparse
55

6-
from muse_as_service.tokenizer.tokenizer import (
7-
get_tokenizer_from_saved_model,
8-
parse_saved_model,
9-
tokenize,
10-
)
6+
from .tokenizer import get_tokenizer_from_saved_model, parse_saved_model, tokenize
117

128

139
def get_sentence_parser() -> reqparse.RequestParser:
File renamed without changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
from .tokenizer import get_tokenizer_from_saved_model, parse_saved_model, tokenize
2+
3+
__all__ = [
4+
"get_tokenizer_from_saved_model",
5+
"parse_saved_model",
6+
"tokenize",
7+
]
File renamed without changes.

tests/test_auth.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
import requests
66
from flask import Flask
77

8-
from muse_as_service import MUSEClient
9-
from muse_as_service.app import app
8+
from src.muse_as_service import MUSEClient
9+
from src.muse_as_service.app import app
1010

1111

1212
class TestAuth(flask_testing.TestCase):

tests/test_database.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import unittest
22

3-
from muse_as_service.app import app # noqa: F401
4-
from muse_as_service.database.database import UserModel
3+
from src.muse_as_service.app import app # noqa: F401
4+
from src.muse_as_service.database import UserModel
55

66

77
class TestDatabase(unittest.TestCase):

tests/test_usage.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
import numpy as np
55
from flask import Flask
66

7-
from muse_as_service import MUSEClient
8-
from muse_as_service.app import app
7+
from src.muse_as_service import MUSEClient
8+
from src.muse_as_service.app import app
99

1010

1111
class TestUsage(flask_testing.TestCase):

0 commit comments

Comments
 (0)