Giter Club home page Giter Club logo

spacy-universal-sentence-encoder's Introduction

Tests Downloads Current Release Version pypi Version Coverage Status Code style: black

Spacy - Universal Sentence Encoder

Make use of Google's Universal Sentence Encoder directly within SpaCy. This library lets you embed Docs, Spans and Tokens from the Universal Sentence Encoder family available on TensorFlow Hub.

For using sentence-BERT in spaCy, see https://github.com/MartinoMensio/spacy-sentence-bert

Motivation

There are many different reasons to not always use BERT. For example to have embeddings that are tuned specifically for another task (e.g. sentence similarity). See this very useful blog article: https://blog.floydhub.com/when-the-best-nlp-model-is-not-the-best-choice/

The Universal Sentence Encoder is trained on different tasks which are more suited to identifying sentence similarity. Google AI blog paper

This library uses the user_hooks of spaCy to use an external model for the vectors, in this case a simple wrapper to the models available on TensorFlow Hub.

Install

You can install this library from:

  • github: pip install git+https://github.com/MartinoMensio/spacy-universal-sentence-encoder.git
  • pyPI: pip install spacy-universal-sentence-encoder

Compatibility:

  • python:
    • 3.6: compatible but not actively tested
    • 3.7/3.8/3.9/3.10: compatible and actively tested
    • 3.11 compatible but relies on rc version of tensorflow-text for multilingual models
  • tensorflow>=2.4.0,<3.0.0
  • spacy>=3.0.0,<4.0.0 (SpaCy v3 API changed a lot from v2)

To use the multilingual version of the models, you need to install the extra named multi with the command: pip install spacy-universal-sentence-encoder[multi]. This installs the dependency tensorflow-text that is required to run the multilingual models. Note that tensorflow-text is currently in RC version for python3.11.

In alternative, you can install the following standalone pre-packaged models with pip. Each model can be installed independently:

model name source pip package
en_use_md https://tfhub.dev/google/universal-sentence-encoder pip install https://github.com/MartinoMensio/spacy-universal-sentence-encoder/releases/download/v0.4.6/en_use_md-0.4.6.tar.gz#en_use_md-0.4.6
en_use_lg https://tfhub.dev/google/universal-sentence-encoder-large pip install https://github.com/MartinoMensio/spacy-universal-sentence-encoder/releases/download/v0.4.6/en_use_lg-0.4.6.tar.gz#en_use_lg-0.4.6
xx_use_md https://tfhub.dev/google/universal-sentence-encoder-multilingual pip install https://github.com/MartinoMensio/spacy-universal-sentence-encoder/releases/download/v0.4.6/xx_use_md-0.4.6.tar.gz#xx_use_md-0.4.6
xx_use_lg https://tfhub.dev/google/universal-sentence-encoder-multilingual-large pip install https://github.com/MartinoMensio/spacy-universal-sentence-encoder/releases/download/v0.4.6/xx_use_lg-0.4.6.tar.gz#xx_use_lg-0.4.6

In addition, also CMLM models are now available:

model name source pip package
en_use_cmlm_md https://tfhub.dev/google/universal-sentence-encoder-cmlm/en-base pip install https://github.com/MartinoMensio/spacy-universal-sentence-encoder/releases/download/v0.4.6/en_use_cmlm_md-0.4.6.tar.gz#en_use_cmlm_md-0.4.6
en_use_cmlm_lg https://tfhub.dev/google/universal-sentence-encoder-cmlm/en-large pip install https://github.com/MartinoMensio/spacy-universal-sentence-encoder/releases/download/v0.4.6/en_use_cmlm_lg-0.4.6.tar.gz#en_use_cmlm_lg-0.4.6
xx_use_cmlm https://tfhub.dev/google/universal-sentence-encoder-cmlm/multilingual-base pip install https://github.com/MartinoMensio/spacy-universal-sentence-encoder/releases/download/v0.4.6/xx_use_cmlm-0.4.6.tar.gz#xx_use_cmlm-0.4.6
xx_use_cmlm_br https://tfhub.dev/google/universal-sentence-encoder-cmlm/multilingual-base-br pip install https://github.com/MartinoMensio/spacy-universal-sentence-encoder/releases/download/v0.4.6/xx_use_cmlm_br-0.4.6.tar.gz#xx_use_cmlm_br-0.4.6

Usage

Loading the model

If you installed the model standalone packages (see table above) you can use the usual spacy API to load this model:

import spacy
nlp = spacy.load('en_use_md')

Otherwise you need to load the model in the following way:

import spacy_universal_sentence_encoder
nlp = spacy_universal_sentence_encoder.load_model('xx_use_lg')

The third option is to load the model on your existing spaCy pipeline:

import spacy
# this is your nlp object that can be any spaCy model
nlp = spacy.load('en_core_web_sm')

# add the pipeline stage (will be mapped to the most adequate model from the table above, en_use_md)
nlp.add_pipe('universal_sentence_encoder')

In all of the three options, the first time that you load a certain Universal Sentence Encoder model, it will be downloaded from TF Hub (see section below to use an already downloaded model, or to change the location of the model files).

The last option (using nlp.add_pipe) can be customised with the following configurations:

  • use_model_url: allows to use a specific TFHub URL
  • preprocessor_url: for TFHub models that need specific preprocessing with another TFHub model (e.g., see documentation of CMLM models)
  • model_name: to load a specific model instead of mapping the current (language, size) to one of the options in the table above
  • enable_cache: default True, enables an internal cache to avoid embedding the same text (doc/span/token) twice. It makes the computation faster (when enough duplicates are embedded) but has a memory footprint because all the embeddings extracted are kept in the cache
  • debug: default False shows debugging information.

To use the configurations, when adding the pipe stage pass a dict as additional argument, for example:

nlp.add_pipe('universal_sentence_encoder', config={'enable_cache': False})

Use the embeddings

After adding to the pipeline, you can use the embedding models by using the various properties and methods of Docs, Spans and Tokens:

# load as before
import spacy
nlp = spacy.load('en_core_web_lg')
nlp.add_pipe('universal_sentence_encoder')

# get two documents
doc_1 = nlp('Hi there, how are you?')
doc_2 = nlp('Hello there, how are you doing today?')
# Inspect the shape of the Doc, Span and Token vectors
print(doc_1.vector.shape) # the full document representation
print(doc_1[3], doc_1[3].vector.shape) # the word "how"
print(doc_1[3:6], doc_1[3:6].vector.shape) # the span "how are you"

# or use the similarity method that is based on the vectors, on Doc, Span or Token
print(doc_1.similarity(doc_2[0:7]))

Common issues

Here you can find the most common issues with possible solutions.

Using a pre-downloaded model

If you want to use a model that you have already downloaded from TensorFlow Hub, belonging to the Universal Sentence Encoder family, you can use it by doing the following:

  • locate the full path of the folder where you have downloaded and extracted the model. Let's suppose the location is $HOME/tfhub_models
  • rename the folder of the extracted model (the one directly containing the folders variables and the file saved_model.pb) to the sha1 hash of the TFHub model source. The mapping URL / sha1 values is the following:
    • en_use_md: 063d866c06683311b44b4992fd46003be952409c
    • en_use_lg: c9fe785512ca4a1b179831acb18a0c6bfba603dd
    • xx_use_md: 26c892ffbc8d7b032f5a95f316e2841ed4f1608c
    • xx_use_lg: 97e68b633b7cf018904eb965602b92c9f3ad14c9
  • set the environment variable TFHUB_CACHE_DIR to the location containing the renamed folder, for example $HOME/tfhub_models (set it before trying to download the model: export TFHUB_CACHE_DIR=$HOME/tfhub_models)
  • Now load your model and it should see that it was already downloaded

Serialisation

To serialise and deserialise nlp objects, SpaCy does not restore user_hooks after deserialisation, so a call to from_bytes will result in not using the TensorFlow vectors, so the similarities won't be good. For this reason the suggested solution is:

  • serialise with bytes = doc.to_bytes() normally
  • deserialise with spacy_universal_sentence_encoder.doc_from_bytes(nlp, bytes) which will also restore the user hooks

Multiprocessing

This library, relying on TensorFlow, is not fork-safe. This means that if you are using this library inside multiple processes (e.g. with a multiprocessing.pool.Pool), your processes will deadlock. The solutions are:

  • use a thread-based environment (e.g. multiprocessing.pool.ThreadPool)
  • only use this library inside the created processes (first create the processes and then import and use the library)

Using nlp.pipe` with multiple processes

Spacy does not restore user hooks (UserWarning: [W109]) therefore if you use nlp.pipe with multiple processes, you won't be able to use the .vector on doc, span and token. I am developing a workaround.

Utils

To build and upload

# change version
VERSION=0.4.6
# change version references everywhere
# update locally installed package
pip install -r requirements.txt
# build the standalone models (8)
./build_models.sh
# build the archive at dist/spacy_universal_sentence_encoder-${VERSION}.tar.gz
python setup.py sdist
# upload to pypi
twine upload dist/spacy_universal_sentence_encoder-${VERSION}.tar.gz
# upload language packages to github

spacy-universal-sentence-encoder's People

Contributors

martinomensio avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

spacy-universal-sentence-encoder's Issues

How to load a model from TensorFlow Hub?

Hello,

I'm new to spacy and tensorflow. This may be a stupid question, but let me ask you one. I'm getting a ValueError: Model "covid-twitter-bert" not available when trying to load this model(covid-twitter-bert) from TensorFlow Hub. how can i load it?

import spacy_universal_sentence_encoder
nlp = spacy_universal_sentence_encoder.load_model('covid-twitter-bert') # Throws a ValueError: Model "covid-twitter-bert" not available

Thank you!

cant change vocab vector

When I try to change the word embeddings nothing happens

`
import spacy_universal_sentence_encoder
nlp_use = spacy_universal_sentence_encoder.load_model('en_use_lg')

vector = nlp_use('her').vector
nlp_use.vocab.set_vector("Ertha", vector)

print(vector)
print(nlp_use("Ertha"))
`
The two print statements should be equal.

Unable to do pip install.

ERROR: Command errored out with exit status 128: git clone -q ssh://[email protected]/MartinoMensio/spacy-universal-sentence-embedding-tfhub 'C:\Users\ROHIT~1.SIN\AppData\Local\Temp\pip-install-i9wahwsy\universal-sentence-encoder' Check the logs for full command output.

I am getting this error whenever I try to install this using pip.

Retrain models to latest version of Spacy

Hi,

Im bumbing with this warning:
Model 'xx_use_lg' (0.3.2) requires spaCy v2.1,<2 and is incompatible with the current spaCy version (2.3.2)

Can you please retrain the models for this specific version or handle some guidlines to do it?

Thanks.

Update to latest versions of tensorflow and spacy

Hi,

Would it be possible to update your repository to the latest version of tensorflow (2.4) and spacy (>3.0) ?

Indeed, having a RTX 3090 CUDA >=11 is required which implies tensorflow >= 2.4.

Thanks !

How to not reach out to internet when loading model

I do
pip install spacy-universal-sentence-encoder

then in code:

import spacy_universal_sentence_encoder
# load one of the models: ['en_use_md', 'en_use_lg', 'xx_use_md', 'xx_use_lg']
nlp = spacy_universal_sentence_encoder.load_model('en_use_md')

But at that load_model line, the code tries to go out to the internet. I see in the stack trace lin 261 in language.py which is

self.model = hub.load(self.model_url)

Is there a way to prevent this loading from a url and just load the model locally?

How to use this with older version of spaCy?

pip seems to install newer version of spaCy(2.3.1), but I need to use 2.1.x for other pipeline utilities(neuralconf by HF).
However, requirements.txt doesn't list spacy.

Is this package built specifically for spacy>=2.3 or is it just configured to do so?

KeyError when added as a pipe

While the first and second option in the readme for using this works the third option

import spacy
# this is your nlp object that can be any spaCy model
nlp = spacy.load('en_core_web_sm')

# add the pipeline stage (will be mapped to the most adequate model from the table above, en_use_md)
nlp.add_pipe('universal_sentence_encoder')

throws a keyerror of the form

File "/.../spacy_universal_sentence_encoder/language.py", line 77, in use_model_factory
    config = util.configs[model_name]
KeyError: 'en_core_web_sm'

Is this behavior expected?

Thank you for any help.

Library incompatible with latest versions of spaCy and tensorflow

Hello,

This library looks great but, when
I tried installing it on my machine which has the latest version of spaCy (2.3.0) and Tensorflow (2.2).

Unfortunately, I could not get it to work and it seems a number of changes would need to be done to make it compatible.

Should the github artifacts have included models?

The readme mentions:

In alternative, you can install the following standalone pre-packaged models with pip. Each model can be installed independently:

But none of the tarballs on github are big enough to include the models. This is rather confusing. Would you be able to help clarify if there is an intention to be able to use pip to install the models, or do we always need to load the model after pip install?

Either way is fine, but I am not sure how to help suggest improving the clarity without knowing the intention. Thanks!

Related: #27 #9

Accessing Document vectors and computing similarity is too slow without batching

Hi,

I use this library and other Spacy models to create Doc objects.
I use the pipe() method to apply this to a large corpus of text. The main challenge is that accessing the vector of each document is too slow.
Is there a way to get only the vector from applying the model on the text? Or extract the vectors in batches as well?
This problem was raised from the problem of similarity where I couldn't also use the method similarity() on batches but only 1 by 1. Is there a way to compute similarity in batches?

I'm using a 4-core CPU.

I hope my question is clear.

Thanks.

Installing tensorflow-text issue

ERROR: Could not find a version that satisfies the requirement tensorflow-text<2.4.0,>=2.3.0 (from spacy-universal-sentence-encoder) (from versions: none)
ERROR: No matching distribution found for tensorflow-text<2.4.0,>=2.3.0 (from spacy-universal-sentence-encoder)

image

How can I apply tf.function decorator to this interface?

Hi ! Thank you for creating this interface. It works pretty fast for me.
While running the text similarity with "en_use_cmlm_md" model, I found the log that says something about tf.function retracing.
Compared to the original models, the new models (cmlm) are much slower. So I tried to look for any way to improve the speed.
I would assume tf.function could boost up the performance, given that I restrict the shape and datatype of Tensors.

triggered tf.function retracing. Tracing is expensive and the excessive number of tracings is likely due to passing python objects instead of tensors. Also, tf.function has experimental_re
lax_shapes=True option that relaxes argument shapes that can avoid unnecessary retracing. Please refer to https://www.tensorflow.org/tutorials/customization/performance#python_or_tensor_args and https://www.tensorflow.org/api_docs/python/tf/function for more details.

Is there any way that I can increase the performance of calculating semantic similarity by using tf.function on this interface?
It seems your interface would work much faster than what I implemented by the tensorflow hub, given that I solve the problem from the above warning logs on this interface.
Cheers !

sentencize & encode

Hi, I'm trying to set up a pipeline so that I can feed it a chunk of text, get spacy to sentencize it in the first pipeline component and then embed each sentence with USE in an overwrite_vectors component. However, I just cannot get it to do this. Is there a canonical way of setting up such a pipeline? Or would it be as efficient to just sentencize into an array of sentences and then embed them one by one? USE does have a batch embed as well so maybe that's a better option. What would you recommend?

Problems installing models on SpaCy 2.3.2

I installed the models as per the directions in the README but they are not showing up in Spacy:

✔ Loaded compatibility table

====================== Installed models (spaCy v2.3.2) ======================
ℹ spaCy installation:
/Users/ckm/.pyenv/versions/3.7.5/lib/python3.7/site-packages/spacy

TYPE      NAME                             MODEL                            VERSION                            
package   en-vectors-web-lg                en_vectors_web_lg                2.3.0   ✔
package   en-trf-xlnetbasecased-lg         en_trf_xlnetbasecased_lg         2.3.0   ✔
package   en-trf-robertabase-lg            en_trf_robertabase_lg            2.3.0   ✔
package   en-trf-distilbertbaseuncased-lg   en_trf_distilbertbaseuncased_lg   2.3.0   ✔
package   en-trf-bertbaseuncased-lg        en_trf_bertbaseuncased_lg        2.3.0   ✔
package   en-core-web-sm                   en_core_web_sm                   2.3.1   ✔
package   en-core-web-lg                   en_core_web_lg                   2.3.1   ✔

I'm installing using:
pip install https://github.com/MartinoMensio/spacy-universal-sentence-encoder/releases/download/v0.3.1/en_use_md-0.3.1.tar.gz#en_use_md-0.3.1
and
pip install https://github.com/MartinoMensio/spacy-universal-sentence-encoder/releases/download/v0.3.1/en_use_lg-0.3.1.tar.gz#en_use_lg-0.3.1
both of which complete successfully.

But calling nlp = spacy.load('en_use_md') results in the following error:

/Users/username/.pyenv/versions/3.7.5/lib/python3.7/site-packages/spacy/util.py:275: UserWarning: [W031] Model 'en_use_md' (0.3.1) requires spaCy v2.1,<2 and is incompatible with the current spaCy version (2.3.2). This may lead to unexpected results or runtime errors. To resolve this, download a newer compatible model or retrain your custom model with the current spaCy version. For more details and available updates, run: python -m spacy validate

It then downloads what seems to be an updated version:
Downloaded https://tfhub.dev/google/universal-sentence-encoder/4, Total size: 987.47MB

But, as soon as any data is loading, I get the following error:

File "_packer.pyx", line 282, in srsly.msgpack._packer.Packer._pack
TypeError: can not serialize 'TFHubWrapper' object

(traceback removed for shortness)

Not sure where to go from here...

installation downloads model but to a tmp folder

This line https://github.com/MartinoMensio/spacy-universal-sentence-encoder-tfhub/blob/e746687dcf084bd5cf7ad0e3012b6388d0fe92c7/setup.py#L2 makes the tfhub download the model to a folder during the installation of the package but then the models folder doesn't get copied when building the wheel. I need to investigate on how a package gets installed.
In this way the model would be already downloaded in venv/lib/python3.7/site-packages/universal_sentence_encoder/models and every single run would use the cache.

Deadlock when use Similarity with multiprocessing pool

Hello,

I really like the idea to combine spacy with google stuff, thanks! I got some seemingly random deadlock problem...

I am basically doing n*(n-1)/2 comparison on 50K papers by their titles and abstracts on a server with 32 cores. I tired single-thread and find no problem among a few tens of Ks, but the deadlock happens almost right away when we I ran the following code. Do you have any suggestions? BTW, I also tried processes=1... it does not work...

def simCount(row):  
    return [row[0], row[3], row[2], row[5], nlp(row[1]).similarity(nlp(row[4]))]  

with Pool(processes=25) as p:
    with tqdm(total=count, desc='Testing') as pbar:
        for idx_left, row_left in _sim_tst.iterrows():
/*Some pandas frame arrangement*/
            for simscore in p.imap_unordered(simCount, _4sim.values.tolist()):  
                ssrn_simscore.append(simscore)
                pbar.update()

Many thanks!

Can we load the model from a local path

Hi,

Thanks for developing spacy USE.

Rather than download a model, can we also save/load a model from a local folder?

or there is a workaround.

I need to use and push a model to a Google Cloud Run's container.

Thanks for your help in advance.

Lu.

Avoiding OOM errors

Hi, I installed this via pip to try it out, and I'm getting OOM errors like this:

2022-09-08 16:35:25.958426: W tensorflow/core/framework/op_kernel.cc:1780] OP_REQUIRES failed at matmul_op_impl.h:728 : RESOURCE_EXHAUSTED: OOM when allocating tensor with shape[1,8,70151,70151] and type float on /job:localhost/replica:0/task:0/device:CPU:0 by allocator cpu

Is there a way I can tell spacy to tell tensorflow that it's OK to use more memory?

Universal sentence encoder unsupervised resume training

I want to train universal sentence encoder on list of sentences about 24000 when those sentences were provided without labels. Can you please tell me how you did it with Spacy. I need to build a new model with new data.

TFLite support?

We're playing around with running this on the edge and we'd appreciate a version with fewer dependencies - perhaps a version which only depends on tflite.

  • Has anyone had success running this model with tflite?
  • Would you accept a PR with a feature-flag for tflite inference and no model download?

ValueError when loading the model

Hi Martino,

I am relatively new to all of this. I tried to load the model in all three options you mentioned in the readme. However, I receive the following error:

ValueError: [E002] Can't find factory for 'universal_sentence_encoder' for language English (en). This usually happens when spaCy calls nlp.create_pipe with a custom component name that's not registered on the current language class. If you're using a Transformer, make sure to install 'spacy-transformers'. If you're using a custom component, make sure you've added the decorator @Language.component (for function components) or @Language.factory (for class components).

Could you help me out?

Kind regards,
Caya de Haas

Is this only for English?

I am curious if this can be used with another language as long as the model corresponds to that language? Currently I am doing work in Spanish and have been using the news es model.

Thanks!

How to use this with a downloaded model?

Hello,

I am trying to use this inside of a Docker image. I have downloaded the model separately from here, and I have performed the pip install https://github.com/MartinoMensio/spacy-universal-sentence-encoder/releases/download/v0.3.1/en_use_lg-0.3.1.tar.gz#en_use_lg-0.3.1 as a RUN command in my Dockerfile.

I want to be able to load and use the model that I downloaded externally, but I don't know how to load it. When I use the following, it redownloads the model; I don't know how to tell it to load the one I downloaded manually and added to the Docker image:

# This downloads the model
nlp = spacy.load('en_use_lg')

I tried the following:

nlp = spacy.load("./universal-sentence-encoder-large_5.tar.gz")
# Untarred the file
nlp = spacy.load("./universal-sentence-encoder-large_5")

Both complain that it cannot find meta.json.
Can you help me?
Thanks!

SpaCy versions required for en_use_lg-0.4.3

I have a project that requires spacy==3.2.1, and I want to include en_use_lg-0.4.3 in the project as well.
The spaCy requirements specified for the large model are "spacy_version":">=3.0.3,<3.1.0", which is incompatible with the requirement I already have (3.2.1).
I tried changing it locally to "spacy_version":">=3.0.3,<=3.2.1", and installed with no problem, and so I was hoping you could update the versions to support spaCy up to the most recent compatible stable version (at least 3.2.1).

Old version model

It is a amazing work! Appreciate your hard work.
I'm met the downloaded model problem, but with the help of https://github.com/MartinoMensio/spacy-universal-sentence-encoder/issues/9#issue-685821614, It work. thanks
however, I met another problem, I am trying use the model https://tfhub.dev/google/universal-sentence-encoder-large/4, It is not the latest version,I got the models https://storage.googleapis.com/tfhub-modules/google/universal-sentence-encoder-large/4.tar.gz via offline, and get sha1: f4ea2eb4a9fd72946209ef45271146fae070fb29, export right path

import spacy nlp=spay.load('en_use_lg')

but it can't work
I guess if the model name is incorrect

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.