GithubHelp home page GithubHelp logo

jina-ai / jina Goto Github PK

View Code? Open in Web Editor NEW
20.0K 207.0 2.2K 1.34 GB

☁️ Build multimodal AI applications with cloud-native stack

Home Page: https://docs.jina.ai

License: Apache License 2.0

Python 96.94% Shell 0.84% Dockerfile 0.48% Go 1.65% C 0.09%
neural-search cloud-native deep-learning machine-learning framework grpc kubernetes multimodal mlops pipeline

jina's Introduction

Jina logo: Build multimodal AI services via cloud native technologies · Model Serving · Generative AI · Neural Search · Cloud Native

Build multimodal AI applications with cloud-native technologies

PyPI PyPI - Downloads from official pypistats Github CD status

Jina lets you build multimodal AI services and pipelines that communicate via gRPC, HTTP and WebSockets, then scale them up and deploy to production. You can focus on your logic and algorithms, without worrying about the infrastructure complexity.

Jina provides a smooth Pythonic experience for serving ML models transitioning from local deployment to advanced orchestration frameworks like Docker-Compose, Kubernetes, or Jina AI Cloud. Jina makes advanced solution engineering and cloud-native technologies accessible to every developer.

Wait, how is Jina different from FastAPI? Jina's value proposition may seem quite similar to that of FastAPI. However, there are several fundamental differences:

Data structure and communication protocols

  • FastAPI communication relies on Pydantic and Jina relies on DocArray allowing Jina to support multiple protocols to expose its services. The support for gRPC protocol is specially useful for data intensive applications as for embedding services where the embeddings and tensors can be more efficiently serialized.

Advanced orchestration and scaling capabilities

  • Jina allows you to easily containerize and orchestrate your services and models, providing concurrency and scalability.
  • Jina lets you deploy applications formed from multiple microservices that can be containerized and scaled independently.

Journey to the cloud

  • Jina provides a smooth transition from local development (using DocArray) to local serving using Deployment and Flow to having production-ready services by using Kubernetes capacity to orchestrate the lifetime of containers.
  • By using Jina AI Cloud you have access to scalable and serverless deployments of your applications in one command.

Install

pip install jina

Find more install options on Apple Silicon/Windows.

Get Started

Basic Concepts

Jina has three fundamental layers:

  • Data layer: BaseDoc and DocList (from DocArray) are the input/output formats in Jina.
  • Serving layer: An Executor is a Python class that transforms and processes Documents. By simply wrapping your models into an Executor, you allow them to be served and scaled by Jina. Gateway is the service making sure connecting all Executors inside a Flow.
  • Orchestration layer: Deployment serves a single Executor, while a Flow serves Executors chained into a pipeline.

The full glossary is explained here.

Serve AI models

Let's build a fast, reliable and scalable gRPC-based AI service. In Jina we call this an Executor. Our simple Executor will wrap the StableLM LLM from Stability AI. We'll then use a Deployment to serve it.

Note A Deployment serves just one Executor. To combine multiple Executors into a pipeline and serve that, use a Flow.

Let's implement the service's logic:

executor.py
from jina import Executor, requests
from docarray import DocList, BaseDoc

from transformers import pipeline


class Prompt(BaseDoc):
    text: str


class Generation(BaseDoc):
    prompt: str
    text: str


class StableLM(Executor):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.generator = pipeline(
            'text-generation', model='stabilityai/stablelm-base-alpha-3b'
        )

    @requests
    def generate(self, docs: DocList[Prompt], **kwargs) -> DocList[Generation]:
        generations = DocList[Generation]()
        prompts = docs.text
        llm_outputs = self.generator(prompts)
        for prompt, output in zip(prompts, llm_outputs):
            generations.append(Generation(prompt=prompt, text=output))
        return generations

Then we deploy it with either the Python API or YAML:

Python API: deployment.py YAML: deployment.yml
from jina import Deployment
from executor import StableLM

dep = Deployment(uses=StableLM, timeout_ready=-1, port=12345)

with dep:
    dep.block()
jtype: Deployment
with:
  uses: StableLM
  py_modules:
    - executor.py
  timeout_ready: -1
  port: 12345

And run the YAML Deployment with the CLI: jina deployment --uses deployment.yml

Use Jina Client to make requests to the service:

from jina import Client
from docarray import DocList, BaseDoc


class Prompt(BaseDoc):
    text: str


class Generation(BaseDoc):
    prompt: str
    text: str


prompt = Prompt(
    text='suggest an interesting image generation prompt for a mona lisa variant'
)

client = Client(port=12345)  # use port from output above
response = client.post(on='/', inputs=[prompt], return_type=DocList[Generation])

print(response[0].text)
a steampunk version of the Mona Lisa, incorporating mechanical gears, brass elements, and Victorian era clothing details

Note In a notebook, you can't use deployment.block() and then make requests to the client. Please refer to the Colab link above for reproducible Jupyter Notebook code snippets.

Build a pipeline

Sometimes you want to chain microservices together into a pipeline. That's where a Flow comes in.

A Flow is a DAG pipeline, composed of a set of steps, It orchestrates a set of Executors and a Gateway to offer an end-to-end service.

Note If you just want to serve a single Executor, you can use a Deployment.

For instance, let's combine our StableLM language model with a Stable Diffusion image generation model. Chaining these services together into a Flow will give us a service that will generate images based on a prompt generated by the LLM.

text_to_image.py
import numpy as np
from jina import Executor, requests
from docarray import BaseDoc, DocList
from docarray.documents import ImageDoc


class Generation(BaseDoc):
    prompt: str
    text: str


class TextToImage(Executor):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        from diffusers import StableDiffusionPipeline
        import torch

        self.pipe = StableDiffusionPipeline.from_pretrained(
            "CompVis/stable-diffusion-v1-4", torch_dtype=torch.float16
        ).to("cuda")

    @requests
    def generate_image(self, docs: DocList[Generation], **kwargs) -> DocList[ImageDoc]:
        result = DocList[ImageDoc]()
        images = self.pipe(
            docs.text
        ).images  # image here is in [PIL format](https://pillow.readthedocs.io/en/stable/)
        result.tensor = np.array(images)
        return result

Build the Flow with either Python or YAML:

Python API: flow.py YAML: flow.yml
from jina import Flow
from executor import StableLM
from text_to_image import TextToImage

flow = (
    Flow(port=12345)
    .add(uses=StableLM, timeout_ready=-1)
    .add(uses=TextToImage, timeout_ready=-1)
)

with flow:
    flow.block()
jtype: Flow
with:
    port: 12345
executors:
  - uses: StableLM
    timeout_ready: -1
    py_modules:
      - executor.py
  - uses: TextToImage
    timeout_ready: -1
    py_modules:
      - text_to_image.py

Then run the YAML Flow with the CLI: jina flow --uses flow.yml

Then, use Jina Client to make requests to the Flow:

from jina import Client
from docarray import DocList, BaseDoc
from docarray.documents import ImageDoc


class Prompt(BaseDoc):
    text: str


prompt = Prompt(
    text='suggest an interesting image generation prompt for a mona lisa variant'
)

client = Client(port=12345)  # use port from output above
response = client.post(on='/', inputs=[prompt], return_type=DocList[ImageDoc])

response[0].display()

Easy scalability and concurrency

Why not just use standard Python to build that service and pipeline? Jina accelerates time to market of your application by making it more scalable and cloud-native. Jina also handles the infrastructure complexity in production and other Day-2 operations so that you can focus on the data application itself.

Increase your application's throughput with scalability features out of the box, like replicas, shards and dynamic batching.

Let's scale a Stable Diffusion Executor deployment with replicas and dynamic batching:

  • Create two replicas, with a GPU assigned for each.
  • Enable dynamic batching to process incoming parallel requests together with the same model inference.
Normal Deployment Scaled Deployment
jtype: Deployment
with:
  uses: TextToImage
  timeout_ready: -1
  py_modules:
    - text_to_image.py
jtype: Deployment
with:
  uses: TextToImage
  timeout_ready: -1
  py_modules:
    - text_to_image.py
  env:
   CUDA_VISIBLE_DEVICES: RR
  replicas: 2
  uses_dynamic_batching: # configure dynamic batching
    /default:
      preferred_batch_size: 10
      timeout: 200

Assuming your machine has two GPUs, using the scaled deployment YAML will give better throughput compared to the normal deployment.

These features apply to both Deployment YAML and Flow YAML. Thanks to the YAML syntax, you can inject deployment configurations regardless of Executor code.

Deploy to the cloud

Containerize your Executor

In order to deploy your solutions to the cloud, you need to containerize your services. Jina provides the Executor Hub, the perfect tool to streamline this process taking a lot of the troubles with you. It also lets you share these Executors publicly or privately.

You just need to structure your Executor in a folder:

TextToImage/
├── executor.py
├── config.yml
├── requirements.txt
config.yml requirements.txt
jtype: TextToImage
py_modules:
  - executor.py
metas:
  name: TextToImage
  description: Text to Image generation Executor based on StableDiffusion
  url:
  keywords: []
diffusers
accelerate
transformers

Then push the Executor to the Hub by doing: jina hub push TextToImage.

This will give you a URL that you can use in your Deployment and Flow to use the pushed Executors containers.

jtype: Flow
with:
    port: 12345
executors:
  - uses: jinai+docker://<user-id>/StableLM
  - uses: jinai+docker://<user-id>/TextToImage

Get on the fast lane to cloud-native

Using Kubernetes with Jina is easy:

jina export kubernetes flow.yml ./my-k8s
kubectl apply -R -f my-k8s

And so is Docker Compose:

jina export docker-compose flow.yml docker-compose.yml
docker-compose up

Note You can also export Deployment YAML to Kubernetes and Docker Compose.

That's not all. We also support OpenTelemetry, Prometheus, and Jaeger.

What cloud-native technology is still challenging to you? Tell us and we'll handle the complexity and make it easy for you.

Deploy to JCloud

You can also deploy a Flow to JCloud, where you can easily enjoy autoscaling, monitoring and more with a single command.

First, turn the flow.yml file into a JCloud-compatible YAML by specifying resource requirements and using containerized Hub Executors.

Then, use jina cloud deploy command to deploy to the cloud:

wget https://raw.githubusercontent.com/jina-ai/jina/master/.github/getting-started/jcloud-flow.yml
jina cloud deploy jcloud-flow.yml

Warning

Make sure to delete/clean up the Flow once you are done with this tutorial to save resources and credits.

Read more about deploying Flows to JCloud.

Streaming for LLMs

Large Language Models can power a wide range of applications from chatbots to assistants and intelligent systems. However, these models can be heavy and slow and your users want systems that are both intelligent and fast!

Large language models work by turning your questions into tokens and then generating new token one at a time until it decides that generation should stop. This means you want to stream the output tokens generated by a large language model to the client. In this tutorial, we will discuss how to achieve this with Streaming Endpoints in Jina.

Service Schemas

The first step is to define the streaming service schemas, as you would do in any other service framework. The input to the service is the prompt and the maximum number of tokens to generate, while the output is simply the token ID:

from docarray import BaseDoc


class PromptDocument(BaseDoc):
    prompt: str
    max_tokens: int


class ModelOutputDocument(BaseDoc):
    token_id: int
    generated_text: str

Service initialization

Our service depends on a large language model. As an example, we will use the gpt2 model. This is how you would load such a model in your executor

from jina import Executor, requests
from transformers import GPT2Tokenizer, GPT2LMHeadModel
import torch

tokenizer = GPT2Tokenizer.from_pretrained('gpt2')


class TokenStreamingExecutor(Executor):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.model = GPT2LMHeadModel.from_pretrained('gpt2')

Implement the streaming endpoint

Our streaming endpoint accepts a PromptDocument as input and streams ModelOutputDocuments. To stream a document back to the client, use the yield keyword in the endpoint implementation. Therefore, we use the model to generate up to max_tokens tokens and yield them until the generation stops:

class TokenStreamingExecutor(Executor):
    ...

    @requests(on='/stream')
    async def task(self, doc: PromptDocument, **kwargs) -> ModelOutputDocument:
        input = tokenizer(doc.prompt, return_tensors='pt')
        input_len = input['input_ids'].shape[1]
        for _ in range(doc.max_tokens):
            output = self.model.generate(**input, max_new_tokens=1)
            if output[0][-1] == tokenizer.eos_token_id:
                break
            yield ModelOutputDocument(
                token_id=output[0][-1],
                generated_text=tokenizer.decode(
                    output[0][input_len:], skip_special_tokens=True
                ),
            )
            input = {
                'input_ids': output,
                'attention_mask': torch.ones(1, len(output[0])),
            }

Learn more about streaming endpoints from the Executor documentation.

Serve and send requests

The final step is to serve the Executor and send requests using the client. To serve the Executor using gRPC:

from jina import Deployment

with Deployment(uses=TokenStreamingExecutor, port=12345, protocol='grpc') as dep:
    dep.block()

To send requests from a client:

import asyncio
from jina import Client


async def main():
    client = Client(port=12345, protocol='grpc', asyncio=True)
    async for doc in client.stream_doc(
        on='/stream',
        inputs=PromptDocument(prompt='what is the capital of France ?', max_tokens=10),
        return_type=ModelOutputDocument,
    ):
        print(doc.generated_text)


asyncio.run(main())
The
The capital
The capital of
The capital of France
The capital of France is
The capital of France is Paris
The capital of France is Paris.

Support

Join Us

Jina is backed by Jina AI and licensed under Apache-2.0.

jina's People

Contributors

alaeddine-13 avatar alexcg1 avatar anish2197 avatar bhavsarpratik avatar bwanglzu avatar catstark avatar cristianmtr avatar davidbp avatar deepankarm avatar delgermurun avatar fhaase2 avatar florian-hoenicke avatar girishc13 avatar hanxiao avatar jackmin801 avatar jacobowitz avatar jina-bot avatar joanfm avatar johannesmessner avatar mapleeit avatar maximilianwerk avatar nan-wang avatar nomagick avatar numb3r3 avatar rutujasurve94 avatar samsja avatar shivam-raj avatar yongxuanzhang avatar yueliu1415926 avatar zac-li 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  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

jina's Issues

getter method is missing in CompoundExecutor.components

this leads to the following exception

compound_c@3378[E][pea:run:270]:unknown exception: list indices must be integers or slices, not str
Traceback (most recent call last):
  File "/Users/nanwang/Codes/jina-ai/jina/jina/peapods/pea.py", line 252, in run
    self.post_init()
  File "/Users/nanwang/Codes/jina-ai/jina/jina/peapods/pea.py", line 288, in post_init
    self.load_executor()
  File "/Users/nanwang/Codes/jina-ai/jina/jina/peapods/pea.py", line 167, in load_executor
    self.executor.attach(pea=self)
  File "/Users/nanwang/Codes/jina-ai/jina/jina/executors/__init__.py", line 528, in attach
    d.attach(executor=self, *args, **kwargs)
  File "/Users/nanwang/Codes/jina-ai/jina/jina/drivers/__init__.py", line 169, in attach
    self._exec = executor.components[self._executor_name]
TypeError: list indices must be integers or slices, not str

The `as_update_method` decorator is not working for customized executors

DummyIndexer inherits everything from NumpyIndexer except add(). During indexing, the add() function is DummyIndexer is not wrapped by as_update_method(). The add() function is expected to be wrapped in executors/init.py::register_class().

class DummyIndexer(NumpyIndexer):
    # the add() function is simply copied from NumpyIndexer
    def add(self, keys: 'np.ndarray', vectors: 'np.ndarray', *args, **kwargs):
        if len(vectors.shape) != 2:
            raise ValueError('vectors shape %s is not valid, expecting "vectors" to have rank of 2' % vectors.shape)

        if not self.num_dim:
            self.num_dim = vectors.shape[1]
            self.dtype = vectors.dtype.name
        elif self.num_dim != vectors.shape[1]:
            raise ValueError(
                "vectors' shape [%d, %d] does not match with indexers's dim: %d" %
                (vectors.shape[0], vectors.shape[1], self.num_dim))
        elif self.dtype != vectors.dtype.name:
            raise TypeError(
                "vectors' dtype %s does not match with indexers's dtype: %s" %
                (vectors.dtype.name, self.dtype))
        elif keys.shape[0] != vectors.shape[0]:
            raise ValueError('number of key %d not equal to number of vectors %d' % (keys.shape[0], vectors.shape[0]))
        elif self.key_dtype != keys.dtype.name:
            raise TypeError(
                "keys' dtype %s does not match with indexers keys's dtype: %s" %
                (keys.dtype.name, self.key_dtype))

        self.write_handler.write(vectors.tobytes())
        self.key_bytes += keys.tobytes()
        self.key_dtype = keys.dtype.name
        self._size += keys.shape[0]

implement PaddleHub encoder

image classification

PaddleHub has 14 types of models (17 models in total)

  1. Xception
  2. VGG
  3. ShuffleNet V2
  4. ResNeXt
    • ResNeXt_vd
    • SE_ResNeXt
    • ResNeXt_wsl
    • ResNeXt
  5. ResNet
    • ResNet V2
  6. PNASNet
  7. Mobilenet_v2
  8. Inception_V4
  9. GoogleNet
  10. EfficientNet
  11. DPN
  12. DenseNet
  13. DarkNet
  14. AlexNet

图像生成

使用GAN的隐层变量表示图片

  1. STGAN
  2. StarGAN
  3. CycleGAN
  4. AttGAN

discussion

  • 目标检测类目下的模型作为 transformer

    1. YOLOv3
    2. Ultra-Light-Fast-Generic-Face-Detector
    3. SSD
    4. PyramidBox
    5. faster_rcnn
  • 图像分割类目下的模型作为 transformer

    1. deeplabv3p
    2. ACE2P
  • 关键点检测类目下的模型输出需要配合embedding使用

    1. pos_resnet50

reference:

https://www.paddlepaddle.org.cn/hublist

Ideas on NLP demos

principle

  1. The demo must be AWESOME. We must show that we are way better than conventional search engines. Specifically, we need to show something that the old-school search engines can NOT do.
  2. The demo must be simple and easy to reproduce.
  3. The demo should present good results.
  4. The data and the model should be small, i.e. less than 300MB.
  5. The data should be neutral, non-racial, and non-offensive. For example, Hate speech identification is a bad idea.
  6. The data should be public available. No need to register or login.
  7. The data don't need a lot of munging.
  8. The quality of the search results should be easy to judge.
  9. The search task should be meaningful and useful.

Potential dataset

  1. Amazon Food Review, 240MB
  2. SouthParkData
  3. Urban dictionary words

demo on a multilingual search

With the help of a multilingual pretrained model, we can do cross language search. The quality of the results is in doubt.

implement torchvision encoder

image classification

There are 12 models in the torchvision.

  1. AlexNet
  2. VGG
  3. ResNet
  4. SqueezeNet
  5. DenseNet
  6. Inception v3
  7. GoogLeNet
  8. ShuffleNet v2
  9. MobileNet v2
  10. ResNeXt
  11. Wide ResNet
  12. MNASNet

discussion

  • semantic segmentaion models can be used for transformer

    1. FCN ResNet101
    2. DeepLabV3 ResNet101
  • object detection models can be used for transformer

    1. Faster R-CNN ResNet-50 FPN
    2. Mask R-CNN ResNet-50 FPN

reference

https://pytorch.org/docs/stable/torchvision/models.html

removing bert-for-tf2 from extra-requirements.txt

i fixed the python version requirements in extra-requirements.txt. This should fix the unit test in python 3.7

but the dependency of bert-for-tf2 requires tensorflow to be installed. This is overkill. In order to use a tokenizer for bert, one need to install almost pytorch, paddlepaddle and tensorflow?? Apparently bert-for-tf2 is badly written

https://github.com/kpe/bert-for-tf2/

It is also not official.

Action point

Remove it from jina, we don't want this overkill yet trivial function as a dependency. Write a simple function if possible.

figure out why ruamel.yaml return strange error under non-x64 arch

docker buildx build --platform linux/arm64 -t jinaai/jina:master-multiarch -o type=registry --file ./Dockerfiles/debianx.Dockerfile --progress plain .

AttributeError: 'NoneType' object has no attribute 'anchor'

#12 7.392     node = self.compose_node(None, None)
#12 7.392   File "/usr/local/lib/python3.7/site-packages/ruamel/yaml/composer.py", line 120, in compose_node
#12 7.392     anchor = event.anchor
#12 7.392 AttributeError: 'NoneType' object has no attribute 'anchor'

Complete trace:

#12 7.392 {'is_trained': False, 'is_updated': False, 'batch_size': None, 'workspace': '$PWD', 'name': None, 'on_gpu': False, 'warn_unnamed': False, 'max_snapshot': 0, 'py_modules': None, 'replica_id': '{root.metas.replica_id}', 'separated_workspace': '{root.metas.separated_workspace}', 'replica_workspace': '{root.metas.workspace}/{root.metas.name}-{root.metas.replica_id}'}
#12 7.392     router@22[E][pea:run:247]:unknown exception: 'NoneType' object has no attribute 'anchor'
#12 7.392 Traceback (most recent call last):
#12 7.392   File "/usr/local/lib/python3.7/site-packages/jina/peapods/pea.py", line 217, in run
#12 7.392     self.post_init()
#12 7.392   File "/usr/local/lib/python3.7/site-packages/jina/peapods/pea.py", line 269, in post_init
#12 7.392     self.load_executor()
#12 7.392   File "/usr/local/lib/python3.7/site-packages/jina/peapods/pea.py", line 158, in load_executor
#12 7.392     self.args.separated_workspace, self.replica_id)
#12 7.392   File "/usr/local/lib/python3.7/site-packages/jina/executors/__init__.py", line 396, in load_config
#12 7.392     return yaml.load(tmp_s)
#12 7.392   File "/usr/local/lib/python3.7/site-packages/ruamel/yaml/main.py", line 343, in load
#12 7.392     return constructor.get_single_data()
#12 7.392   File "/usr/local/lib/python3.7/site-packages/ruamel/yaml/constructor.py", line 113, in get_single_data
#12 7.392     return self.construct_document(node)
#12 7.392   File "/usr/local/lib/python3.7/site-packages/ruamel/yaml/constructor.py", line 118, in construct_document
#12 7.392     data = self.construct_object(node)
#12 7.392   File "/usr/local/lib/python3.7/site-packages/ruamel/yaml/constructor.py", line 146, in construct_object
#12 7.392     data = self.construct_non_recursive_object(node)
#12 7.392   File "/usr/local/lib/python3.7/site-packages/ruamel/yaml/constructor.py", line 181, in construct_non_recursive_object
#12 7.392     data = constructor(self, node)
#12 7.392   File "/usr/local/lib/python3.7/site-packages/jina/executors/__init__.py", line 438, in from_yaml
#12 7.392     return cls._get_instance_from_yaml(constructor, node, stop_on_import_error)[0]
#12 7.392   File "/usr/local/lib/python3.7/site-packages/jina/executors/__init__.py", line 443, in _get_instance_from_yaml
#12 7.392     constructor, node, deep=True)
#12 7.392   File "/usr/local/lib/python3.7/site-packages/ruamel/yaml/constructor.py", line 440, in construct_mapping
#12 7.392     return BaseConstructor.construct_mapping(self, node, deep=deep)
#12 7.392   File "/usr/local/lib/python3.7/site-packages/ruamel/yaml/constructor.py", line 255, in construct_mapping
#12 7.392     value = self.construct_object(value_node, deep=deep)
#12 7.392   File "/usr/local/lib/python3.7/site-packages/ruamel/yaml/constructor.py", line 146, in construct_object
#12 7.392     data = self.construct_non_recursive_object(node)
#12 7.392   File "/usr/local/lib/python3.7/site-packages/ruamel/yaml/constructor.py", line 188, in construct_non_recursive_object
#12 7.392     for _dummy in generator:
#12 7.392   File "/usr/local/lib/python3.7/site-packages/ruamel/yaml/constructor.py", line 723, in construct_yaml_map
#12 7.392     value = self.construct_mapping(node)
#12 7.392   File "/usr/local/lib/python3.7/site-packages/ruamel/yaml/constructor.py", line 440, in construct_mapping
#12 7.392     return BaseConstructor.construct_mapping(self, node, deep=deep)
#12 7.392   File "/usr/local/lib/python3.7/site-packages/ruamel/yaml/constructor.py", line 255, in construct_mapping
#12 7.392     value = self.construct_object(value_node, deep=deep)
#12 7.392   File "/usr/local/lib/python3.7/site-packages/ruamel/yaml/constructor.py", line 146, in construct_object
#12 7.392     data = self.construct_non_recursive_object(node)
#12 7.392   File "/usr/local/lib/python3.7/site-packages/ruamel/yaml/constructor.py", line 188, in construct_non_recursive_object
#12 7.392     for _dummy in generator:
#12 7.392   File "/usr/local/lib/python3.7/site-packages/ruamel/yaml/constructor.py", line 723, in construct_yaml_map
#12 7.392     value = self.construct_mapping(node)
#12 7.392   File "/usr/local/lib/python3.7/site-packages/ruamel/yaml/constructor.py", line 440, in construct_mapping
#12 7.392     return BaseConstructor.construct_mapping(self, node, deep=deep)
#12 7.392   File "/usr/local/lib/python3.7/site-packages/ruamel/yaml/constructor.py", line 255, in construct_mapping
#12 7.392     value = self.construct_object(value_node, deep=deep)
#12 7.392   File "/usr/local/lib/python3.7/site-packages/ruamel/yaml/constructor.py", line 146, in construct_object
#12 7.392     data = self.construct_non_recursive_object(node)
#12 7.392   File "/usr/local/lib/python3.7/site-packages/ruamel/yaml/constructor.py", line 188, in construct_non_recursive_object
#12 7.392     for _dummy in generator:
#12 7.392   File "/usr/local/lib/python3.7/site-packages/ruamel/yaml/constructor.py", line 717, in construct_yaml_seq
#12 7.392     data.extend(self.construct_sequence(node))
#12 7.392   File "/usr/local/lib/python3.7/site-packages/ruamel/yaml/constructor.py", line 211, in construct_sequence
#12 7.392     return [self.construct_object(child, deep=deep) for child in node.value]
#12 7.392   File "/usr/local/lib/python3.7/site-packages/ruamel/yaml/constructor.py", line 211, in <listcomp>
#12 7.392     return [self.construct_object(child, deep=deep) for child in node.value]
#12 7.392   File "/usr/local/lib/python3.7/site-packages/ruamel/yaml/constructor.py", line 146, in construct_object
#12 7.392     data = self.construct_non_recursive_object(node)
#12 7.392   File "/usr/local/lib/python3.7/site-packages/ruamel/yaml/constructor.py", line 181, in construct_non_recursive_object
#12 7.392     data = constructor(self, node)
#12 7.392   File "/usr/local/lib/python3.7/site-packages/jina/drivers/__init__.py", line 111, in from_yaml
#12 7.392     return cls._get_instance_from_yaml(constructor, node)
#12 7.392   File "/usr/local/lib/python3.7/site-packages/jina/drivers/__init__.py", line 118, in _get_instance_from_yaml
#12 7.392     obj = cls(**data.get('with', {}))
#12 7.392   File "/usr/local/lib/python3.7/site-packages/jina/executors/decorators.py", line 85, in arg_wrapper
#12 7.392     _defaults = get_default_metas()
#12 7.392   File "/usr/local/lib/python3.7/site-packages/jina/executors/metas.py", line 134, in get_default_metas
#12 7.392     _defaults = yaml.load(fp)  # do not expand variables at here, i.e. DO NOT USE expand_dict(yaml.load(fp))
#12 7.392   File "/usr/local/lib/python3.7/site-packages/ruamel/yaml/main.py", line 343, in load
#12 7.392     return constructor.get_single_data()
#12 7.392   File "/usr/local/lib/python3.7/site-packages/ruamel/yaml/constructor.py", line 111, in get_single_data
#12 7.392     node = self.composer.get_single_node()
#12 7.392   File "/usr/local/lib/python3.7/site-packages/ruamel/yaml/composer.py", line 78, in get_single_node
#12 7.392     document = self.compose_document()
#12 7.392   File "/usr/local/lib/python3.7/site-packages/ruamel/yaml/composer.py", line 101, in compose_document
#12 7.392     node = self.compose_node(None, None)
#12 7.392   File "/usr/local/lib/python3.7/site-packages/ruamel/yaml/composer.py", line 120, in compose_node
#12 7.392     anchor = event.anchor
#12 7.392 AttributeError: 'NoneType' object has no attribute 'anchor'
#12 7.397     router@22[I][zmq:__e:122]:bytes_sent: 0 KB bytes_recv:0 KB

add `jina build` to CLI API

Jina build will build the docker image and do a unit test to make sure this container is valid and usable

Adding remote control support to Jina Flow?

Related to #33

See PR in #35 (JEP-2) Section "Can we support remote Pod in the Flow API?"

JEP-2 rules out the remote control of Jina Flow, but on the second thought, I believe adding remote control may give Jina a competitive advantage over K8s and Docker Swarm: it enables users to use Jina in distributed manner without learning container orchestration. The learning curve of Jina Flow API is much smoother than the counterparts.

So maybe it is a good idea to include remote control in Flow API?

Support remote control using Pod and frontend

  • The SPAWN request contains the args of a Pod.
  • The SPAWN request comes from request_generator in the form of a gRPC request and goes to the frontend.
  • The frontend receives the request and start a Pod
  • All log output of this Pod is redirected back to where it connects with stream

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.