1. Jina 是什么
简单来说 Jina 可以帮助你快速把非结构化数据例如图像,文档视频等,转换为向量数据。并结合 Jina 的其他组件设计,帮助你快速的把向量数据利用起来,实现多模态的数据搜索。
2. Jina 的三个基本概念
Document、Executor 和 Flow 是 Jina 的三个基本概念。
- Document 是基本的数据类型,它的作用就是可以将非结构化数据与向量数据之间进行映射,具体细节会在 DocArray 一章中详细阐述。
- Executor 可以理解为一个 Python 类,代表了 Jina 中的算法单元,比如把图像编码成向量、对结果进行排序等算法等都可以用
- Executor 来表述。 Flow 可以将多个 Executor 连接起来,将他们协调成流水线(pipeline)。
3. Document
Document 是基本的数据类型,与之相关的几个概念统一用DocArray来称呼。DocArray 由三个简单的概念组成:
- Document:一种表示嵌套非结构化数据的数据结构,是 DocArray 的基本数据类型。无论是处理文本、图像、视频、音频、3D、表格或它们的嵌套或组合,都可以用 Document 来表示,从而使得各类数据的结构都非常规整,方便后续处理
- DocumentArray:用于高效访问、处理和理解多个文档的容器,可以保存多个 Document 的列表
- Dataclass:用于直观表示多模式数据的高级API
以下是通过DocArray表示不同数据类型的示例
3.1 Text
3.1.1 导入文本
在 DocArray 中表示文本非常简单
from docarray import Document
Document(text='hello, world.')
如果文本数据较大,或者来自 URI,可以先定义 uri,然后再将文本加载到文档中:
from docarray import Document
d = Document(uri='https://www.w3.org/History/19921103-hypertext/hypertext/README.html')
d.load_uri_to_text()
d.summary()
<Document ('id', 'mime_type', 'text', 'uri') at 3c128f326fbf11ec90821e008a366d49>
也可以使用不同语言的字符:
from docarray import Document
d = Document(text='👋 नमस्ते दुनिया! 你好世界!こんにちは世界! Привет мир!')
3.1.2 分割长文档
我们经常会遇到处理长文本的情况,此时可能会有分割长文本的需求,可以通过chunks来执行此操作。
from docarray import Document
d = Document(text='👋 नमस्ते दुनिया! 你好世界!こんにちは世界! Привет мир!')
d.chunks.extend([Document(text=c) for c in d.text.split('!')])
d.summary()
<Document ('id', 'mime_type', 'text', 'chunks') at 5a12d7a86fbf11ec99a21e008a366d49>
└─ chunks
├─ <Document ('id', 'mime_type', 'text') at 5a12e2346fbf11ec99a21e008a366d49>
├─ <Document ('id', 'mime_type', 'text') at 5a12e2f26fbf11ec99a21e008a366d49>
├─ <Document ('id', 'mime_type', 'text') at 5a12e3886fbf11ec99a21e008a366d49>
├─ <Document ('id', 'mime_type', 'text') at 5a12e41e6fbf11ec99a21e008a366d49>
└─ <Document ('id',) at 5a12e4966fbf11ec99a21e008a366d49>
如上所示,在原始文档下创建了五个子文档,并将它们存储在原始文档的 .chunk 下。
3.1.3 将文本转换为 ndarray
有时需要在进一步计算之前将文本编码为 numpy.ndarray。在 Document 和 DocumentArray 中提供了一些函数,可以完成此操作。
例如,我们有一个包含三个文档的文档数组:
from docarray import DocumentArray, Document
da = DocumentArray(
[
Document(text='hello world'),
Document(text='goodbye world'),
Document(text='hello goodbye'),
]
)
要获取vocabulary,可以使用:
vocab = da.get_vocabulary()
{'hello': 2, 'world': 3, 'goodbye': 4}
这里词汇索引从2开始,是因为0 表示padding,1 表示unknow。 可以进一步使用此词汇将 .text 字段转换为 .tensor:
for d in da:
d.convert_text_to_tensor(vocab)
print(d.tensor)
[2 3]
[4 3]
[2 4]
另外,可以通过max_length参数调整tensor的长度:
from docarray import Document, DocumentArray
da = DocumentArray(
[
Document(text='a short phrase'),
Document(text='word'),
Document(text='this is a much longer sentence'),
]
)
vocab = da.get_vocabulary()
for d in da:
d.convert_text_to_tensor(vocab, max_length=10)
print(d.tensor)
[0 0 0 0 0 0 0 2 3 4]
[0 0 0 0 0 0 0 0 0 5]
[ 0 0 0 0 6 7 2 8 9 10]
还可以使用 DocumentArray 的 .tensors 在ndarray 中一次性获取所有张量。
[[ 0 0 0 0 0 0 0 2 3 4]
[ 0 0 0 0 0 0 0 0 0 5]
[ 0 0 0 0 6 7 2 8 9 10]]
3.1.4 将 ndarray 转换回文本
还可以根据给定的vocabulary将ndarray 转换回文本。
from docarray import Document, DocumentArray
da = DocumentArray(
[
Document(text='a short phrase'),
Document(text='word'),
Document(text='this is a much longer sentence'),
]
)
vocab = da.get_vocabulary()
# encoding
for d in da:
d.convert_text_to_tensor(vocab, max_length=10)
# decoding
for d in da:
d.convert_tensor_to_text(vocab)
print(d.text)
a short phrase
word
this is a much longer sentence
3.1.5 使用特征哈希进行简单的文本匹配
在《傲慢与偏见》中搜索“she entered the room”:
from docarray import Document, DocumentArray
d = Document(uri='https://www.gutenberg.org/files/1342/1342-0.txt').load_uri_to_text()
da = DocumentArray(Document(text=s.strip()) for s in d.text.split('\n') if s.strip())
da.apply(lambda d: d.embed_feature_hashing())
q = (
Document(text='she entered the room')
.embed_feature_hashing()
.match(da, limit=5, exclude_self=True, metric='jaccard', use_scipy=True)
)
print(q.matches[:, ('text', 'scores__jaccard')])
[['staircase, than she entered the breakfast-room, and congratulated',
'of the room.',
'She entered the room with an air more than usually ungracious,',
'entered the breakfast-room, where Mrs. Bennet was alone, than she',
'those in the room.'],
[{'value': 0.6, 'ref_id': 'f47f7448709811ec960a1e008a366d49'},
{'value': 0.6666666666666666, 'ref_id': 'f47f7448709811ec960a1e008a366d49'},
{'value': 0.6666666666666666, 'ref_id': 'f47f7448709811ec960a1e008a366d49'},
{'value': 0.6666666666666666, 'ref_id': 'f47f7448709811ec960a1e008a366d49'},
{'value': 0.7142857142857143, 'ref_id': 'f47f7448709811ec960a1e008a366d49'}]]
未完待续。。。