From a63453bb0474e8ef5ccd55c8a1c04a7059851a53 Mon Sep 17 00:00:00 2001 From: maxwelljin <101249253+maxwelljin@users.noreply.github.com> Date: Mon, 19 Jun 2023 15:59:31 +0800 Subject: [PATCH 1/5] doc: fix vector doc Signed-off-by: maxwelljin <101249253+maxwelljin@users.noreply.github.com> --- docs/user_guide/representing/array.md | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/docs/user_guide/representing/array.md b/docs/user_guide/representing/array.md index 7a49c68ea2d..9a07d649d5a 100644 --- a/docs/user_guide/representing/array.md +++ b/docs/user_guide/representing/array.md @@ -256,20 +256,20 @@ This is where the custom syntax `DocList[DocType]` comes into play. !!! note `DocList[DocType]` creates a custom [`DocList`][docarray.array.doc_list.doc_list.DocList] that can only contain `DocType` Documents. -This syntax is inspired by more statically typed languages, and even though it might offend Python purists, we believe that it is a good user experience to think of an Array of `BaseDoc`s rather than just an array of non-homogenous `BaseDoc`s. +This syntax is inspired by more statically typed languages, and even though it might offend Python purists, we believe that it is a good user experience to think of an Array of `BaseDoc`s rather than just an array of heterogeneous `BaseDoc`s. -That said, `AnyDocArray` can also be used to create a non-homogenous `AnyDocArray`: +That said, `AnyDocArray` can also be used to create a heterogeneous `AnyDocArray`: !!! note - The default `DocList` can be used to create a non-homogenous list of `BaseDoc`. + The default `DocList` can be used to create a heterogeneous list of `BaseDoc`. !!! warning - `DocVec` cannot store non-homogenous `BaseDoc` and always needs the `DocVec[DocType]` syntax. + `DocVec` cannot store heterogeneous `BaseDoc` and always needs the `DocVec[DocType]` syntax. -The usage of a non-homogenous `DocList` is similar to a normal Python list but still offers DocArray functionality +The usage of a heterogeneous `DocList` is similar to a normal Python list but still offers DocArray functionality like [serialization and sending over the wire](../sending/first_step.md). However, it won't be able to extend the API of your custom schema to the Array level. -Here is how you can instantiate a non-homogenous `DocList`: +Here is how you can instantiate a heterogeneous `DocList`: ```python from docarray import BaseDoc, DocList @@ -386,10 +386,10 @@ this means that if you call `docs.image` multiple times, under the hood you will Let's see how it will work with `DocVec`: ```python -from docarray import DocList +from docarray import DocVec import numpy as np -docs = DocList[ImageDoc]( +docs = DocVec[ImageDoc]( [ImageDoc(image=np.random.rand(3, 224, 224)) for _ in range(10)] ) @@ -460,6 +460,8 @@ Both [`DocList`][docarray.array.doc_list.doc_list.DocList] and [`DocVec`][docarr Using nested optional fields differs slightly between DocList and DocVes, so watch out. But in a nutshell: When accessing a nested BaseDoc: + + * DocList will return a list of documents if the field is optional and a DocList if the field is not optional * DocVec will return a DocVec if all documents are there, or None if all docs are None. No mix of docs and None allowed! * DocVec will behave the same for a tensor field instead of a BaseDoc From aaebcbc9b4d95b0a27d4c1edfd09dd37dd30408f Mon Sep 17 00:00:00 2001 From: maxwelljin <101249253+maxwelljin@users.noreply.github.com> Date: Mon, 19 Jun 2023 16:34:54 +0800 Subject: [PATCH 2/5] doc: fix the FastAPI example Signed-off-by: maxwelljin <101249253+maxwelljin@users.noreply.github.com> --- README.md | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 7bc4cab9971..fa09db176cb 100644 --- a/README.md +++ b/README.md @@ -674,16 +674,14 @@ And to seal the deal, let us show you how easily documents slot into your FastAP ```python import numpy as np from fastapi import FastAPI -from httpx import AsyncClient - +from docarray.base_doc import DocArrayResponse from docarray import BaseDoc from docarray.documents import ImageDoc from docarray.typing import NdArray -from docarray.base_doc import DocArrayResponse - class InputDoc(BaseDoc): img: ImageDoc + text: str class OutputDoc(BaseDoc): @@ -691,24 +689,16 @@ class OutputDoc(BaseDoc): embedding_bert: NdArray -input_doc = InputDoc(img=ImageDoc(tensor=np.zeros((3, 224, 224)))) - app = FastAPI() -@app.post("/doc/", response_model=OutputDoc, response_class=DocArrayResponse) +@app.post("/embed/", response_model=OutputDoc, response_class=DocArrayResponse) async def create_item(doc: InputDoc) -> OutputDoc: ## call my fancy model to generate the embeddings doc = OutputDoc( - embedding_clip=np.zeros((100, 1)), embedding_bert=np.zeros((100, 1)) + embedding_clip=doc.image, embedding_bert=doc.text ) return doc - - -async with AsyncClient(app=app, base_url="http://test") as ac: - response = await ac.post("/doc/", data=input_doc.json()) - resp_doc = await ac.get("/docs") - resp_redoc = await ac.get("/redoc") ``` Just like a vanilla Pydantic model! From f4e10fb5608edec5c403c14bf0a6f45b8b565e2c Mon Sep 17 00:00:00 2001 From: maxwelljin <101249253+maxwelljin@users.noreply.github.com> Date: Mon, 19 Jun 2023 16:44:48 +0800 Subject: [PATCH 3/5] docs: improve FastAPI doc Signed-off-by: maxwelljin <101249253+maxwelljin@users.noreply.github.com> --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index fa09db176cb..2b6f6ac5829 100644 --- a/README.md +++ b/README.md @@ -691,12 +691,12 @@ class OutputDoc(BaseDoc): app = FastAPI() +model_img, model_text = SomeEmbeddingModelImage(), SomeEmbeddingModelText() @app.post("/embed/", response_model=OutputDoc, response_class=DocArrayResponse) async def create_item(doc: InputDoc) -> OutputDoc: - ## call my fancy model to generate the embeddings doc = OutputDoc( - embedding_clip=doc.image, embedding_bert=doc.text + embedding_clip=model_img(doc.img.tensor), embedding_bert=model_text(doc.text) ) return doc ``` From 89a69231b9ad2327f738b7667f15066b65180671 Mon Sep 17 00:00:00 2001 From: maxwelljin <101249253+maxwelljin@users.noreply.github.com> Date: Mon, 19 Jun 2023 16:59:50 +0800 Subject: [PATCH 4/5] docs: add dummy embedding function Signed-off-by: maxwelljin <101249253+maxwelljin@users.noreply.github.com> --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 2b6f6ac5829..de82b41ead3 100644 --- a/README.md +++ b/README.md @@ -691,7 +691,7 @@ class OutputDoc(BaseDoc): app = FastAPI() -model_img, model_text = SomeEmbeddingModelImage(), SomeEmbeddingModelText() +model_img, model_text = lambda img: np.zeros((100, 1)), lambda text: np.zeros((100, 1)) @app.post("/embed/", response_model=OutputDoc, response_class=DocArrayResponse) async def create_item(doc: InputDoc) -> OutputDoc: @@ -699,6 +699,10 @@ async def create_item(doc: InputDoc) -> OutputDoc: embedding_clip=model_img(doc.img.tensor), embedding_bert=model_text(doc.text) ) return doc + +async with AsyncClient(app=app, base_url="http://test") as ac: + response = await ac.post("/embed/", data=input_doc.json()) + ``` Just like a vanilla Pydantic model! From c4ef76678a45830acf3d05807c5800dfb367188f Mon Sep 17 00:00:00 2001 From: maxwelljin <101249253+maxwelljin@users.noreply.github.com> Date: Mon, 19 Jun 2023 17:14:06 +0800 Subject: [PATCH 5/5] docs: improve Fast API examples Signed-off-by: maxwelljin <101249253+maxwelljin@users.noreply.github.com> --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index de82b41ead3..bedf00d07bf 100644 --- a/README.md +++ b/README.md @@ -691,7 +691,11 @@ class OutputDoc(BaseDoc): app = FastAPI() -model_img, model_text = lambda img: np.zeros((100, 1)), lambda text: np.zeros((100, 1)) +def model_img(img: ImageTensor) -> NdArray: + return np.zeros((100, 1)) + +def model_text(text: str) -> NdArray: + return np.zeros((100, 1)) @app.post("/embed/", response_model=OutputDoc, response_class=DocArrayResponse) async def create_item(doc: InputDoc) -> OutputDoc: