TA3-TA2通信API的GRPC协议。
项目描述
TA3-TA2 API
该仓库包含一个TA3-TA2 API协议规范及其使用GRPC的实现。API允许TA3请求TA2启动管道搜索过程,使用可选的管道模板,并在找到候选管道后,TA3可以通过管道请求评分、拟合或生成数据。
GRPC协议规范可以自动编译成多种编程语言的实现。有关更多信息,请参阅下面的快速入门,其中包含有关GRPC的详细信息。
API结构
TA3-TA2 API调用定义在核心 GRPC服务中,该服务可在core.proto
文件中找到,所有TA3和TA2系统都应实现并支持它。其他.proto
文件提供了其他标准消息的定义。
Python中用于处理TA3-TA2 API的有用实用工具包含在ta3ta2_api包中。
GRPC编译
GRPC提供工具将协议规范编译成各种目标语言。以下是一些示例。
Go设置
要在Go中设置GRPC和Protocol Buffers,请运行
go get -u github.com/golang/protobuf/proto
go get -u github.com/golang/protobuf/protoc-gen-go
go get -u google.golang.org/grpc
然后安装协议缓冲区编译器
Linux
curl -OL https://github.com/google/protobuf/releases/download/v3.3.0/protoc-3.3.0-linux-x86_64.zip
unzip protoc-3.3.0-linux-x86_64.zip -d protoc3
sudo cp protoc3/bin/protoc /usr/bin/protoc
sudo cp -r protoc3/include /usr/local
OSX
curl -OL https://github.com/google/protobuf/releases/download/v3.3.0/protoc-3.3.0-osx-x86_64.zip
unzip protoc-3.3.0-osx-x86_64.zip -d protoc3
sudo cp protoc3/bin/protoc /usr/bin/protoc
sudo cp -r protoc3/include /usr/local
编译.proto
文件
protoc -I /usr/local/include -I . core.proto --go_out=plugins=grpc:.
生成的core.pb.go
文件实现了消息协议、客户端和服务器。
Python设置
通过pip安装库和工具
python -m pip install grpcio --ignore-installed
python -m pip install grpcio-tools
编译.proto
文件
python -m grpc_tools.protoc -I . --python_out=. --grpc_python_out=. core.proto
创建的 core_pb2.py
文件实现了消息协议,而 core_pb2_grpc.py
实现了客户端和服务器。
JavaScript/Node.js 配置
使用 npm
获取 GRPC 和 Protocol Buffer 包
npm install grpc
npm install google-protobuf
与 Go 安装一样,需要安装协议缓冲编译器
Linux
curl -OL https://github.com/google/protobuf/releases/download/v3.3.0/protoc-3.3.0-linux-x86_64.zip
unzip protoc-3.3.0-linux-x86_64.zip -d protoc3
sudo mv protoc3/bin/protoc /usr/bin/protoc
sudo cp -r protoc3/include /usr/local
OSX
curl -OL https://github.com/google/protobuf/releases/download/v3.3.0/protoc-3.3.0-osx-x86_64.zip
unzip protoc-3.3.0-osx-x86_64.zip -d protoc3
sudo mv protoc3/bin/protoc /usr/bin/protoc
sudo cp -r protoc3/include /usr/local
编译.proto
文件
protoc -I /usr/local/include -I . core.proto --js_out=import_style=commonjs,binary:.
生成的 core_pb.js
文件实现了消息协议、客户端和服务器。
管道
API 围绕管道的概念。管道使用共享的 D3M 管道语言 描述。管道描述在两个地方使用
- 描述 TA3 提供给 TA2 的管道模板。
- 描述 TA2 找回给 TA3 的结果管道。
通常,管道总是以数据集容器值(目前只有一个)作为输入,并预测作为输出。这是 TA2 预期搜索的唯一管道。但 TA3 可以完全指定任何管道供 TA2 执行,而无需任何搜索(包括只有一个原语组成的管道)。
如果管道有相关的问题描述,则这应该适用于管道开始处的数据。这对于部分指定的管道尤其相关;部分指定的管道的问题描述应该描述管道开始处的数据,而不是指定部分结束处的数据。
管道模板
管道模板基于管道描述,只有少数差异
- 模板可以接受 多个 数据集容器值作为输入。
- 有一个特殊的 占位符管道步骤,它指示 TA2 系统在管道模板中插入它找到的标准管道的位置。
- 管道描述中并非所有字段都是合理的(它们将由 TA2 填充)。这些差异通过
pipeline.proto
中的注释进行解释。
占位符管道步骤在管道搜索期间替换为子管道,以形成最终的管道。
管道模板限制
虽然管道模板语言不限制占位符步骤的使用,但我们目前在 TA3-TA2 API 的目的下对以下内容进行限制
- 管道模板中只能有一个占位符步骤,位于管道的顶层(不在子管道内部)。
- 占位符步骤必须只有一个输入,即数据集容器值,以及一个输出,即 Pandas dataframe 中的预测。这样它类似于标准管道。
- 占位符只能是管道的最后一步。
- 所有原语步骤应该具有所有其超参数固定(还可以参考
use_default_values_for_free_hyperparams
标志来控制此要求)。
这些限制实际上意味着管道模板只能指定一个有向无环图的前处理原语,它将一个或多个输入数据集容器值转换为一个 单个 转换后的数据集容器值,这是占位符步骤(及其替代子管道)的输入。对管道模板中可以使用的单个原语类型没有其他限制,尽管在使用给定的原语之前应该评估其下游 TA2 处理的影响。
个体系统可以放宽这些限制。例如,它们可能允许占位符步骤之后有后处理原语步骤。在这种情况下,后处理原语只能将占位符步骤的预测转换成转换后的预测。或者,个体系统可能允许原语步骤具有TA2系统应该调整的自由超参数(参见use_default_values_for_free_hyperparams
标志以可能控制此行为)。我们预计某些TA2系统将能够满足这些放宽的要求,如果可用,TA3可以使用这些,但预计不是每个TA2都能做到。
完全指定的管道
TA3还可以在SearchSolutions
中提供一个完全指定的管道。这是一个没有占位符步骤并且所有超参数都固定的管道描述。
对于具有固定超参数的完全指定管道,TA2将仅检查给定的管道是否有效,并将其返回以直接执行(评分、拟合、调用以生成数据)。这允许在数据上执行固定计算,例如,管道可以仅由具有固定超参数的一个原语组成以执行该原语。此外,此类具有固定超参数的完全指定管道可以具有任何输入和任何输出。(标准管道是从Dataset容器值到预测Pandas data frame的。)当提供非Dataset输入时,TA2应尝试将输入值转换为最接近的容器类型值,例如,将GRPC RAW
列表值转换为具有生成元数据的d3m.container.List
,将读取的CSV文件转换为具有生成元数据的d3m.container.DataFrame
。
个体系统还可以支持所有原语都已指定的管道,但具有自由(可调整)超参数。在这种情况下,TA2将仅调整超参数,并且生成的管道将与给定的管道具有相同的结构,但超参数配置将不同。如果不希望系统有这样的潜在行为,可以将use_default_values_for_free_hyperparams
标志设置为true。
值
一些消息包含可以在TA2和TA3之间传递的数据值。这些值可以通过多种方式传递,并在value.proto
文件中列出。
- 将简单的原始值直接放入消息中。
- 如果值是Dataset容器值,则通过数据集URI读取或写入它。
- 值也可以Python-pickled并存储在URI中或直接在消息中给出。
- 如果值是表格容器值,它也可以存储为CSV文件。
- 值可以存储到共享的Plasma存储中,在这种情况下,值由其Plasma ObjectID表示。
由于并非所有系统都可以或愿意支持所有传递值的方式,并且我们可以在未来扩展它们,API支持通过Hello
调用在TA2和TA3之间进行信号传递,以确定允许/支持哪些值类型。
示例调用流程
基本管道搜索
以下是一个示例调用流程,其中TA3系统在没有预处理或后处理的请求中启动管道搜索,TA2系统通过一系列流式响应返回两个管道。每个管道的响应使用一个GRPC流传输,并且可以交错。客户端随后请求一个的分数。
sequenceDiagram
participant Client
participant ScoreSolution
participant SearchSolutions
Client->>SearchSolutions: SearchSolutionsRequest
SearchSolutions-->>Client: SearchSolutionsResponse { search_id = 057cf5... }
Client->>+SearchSolutions: GetSearchSolutionsResults(GetSearchSolutionsResultsRequest)
SearchSolutions-->>Client: GetSearchSolutionsResultsResponse { solution_id = a5d78d... }
SearchSolutions-->>Client: GetSearchSolutionsResultsResponse { solution_id = b6d5e2... }
Client->>ScoreSolution: ScoreSolutionRequest { a5d78d... }
ScoreSolution-->>Client: ScoreSolutionResponse { request_id = 1d9193... }
Client->>+ScoreSolution: GetScoreSolutionResults(GetScoreSolutionResultsRequest)
ScoreSolution-->>Client: ScoreSolutionResultsResponse { progress = PENDING }
ScoreSolution-->>Client: ScoreSolutionResultsResponse { progress = RUNNING }
ScoreSolution-->>Client: ScoreSolutionResultsResponse { progress = COMPLETED, scores }
ScoreSolution-->>-Client: (ScoreSolution stream ends)
Client->>SearchSolutions: EndSearchSolutions(EndSearchSolutionsRequest)
SearchSolutions-->>Client: EndSearchSolutionsResponse
SearchSolutions-->>-Client: (GetFoundSolutions stream ends)
1. Client: SearchSolutions(SearchSolutionsRequest) // problem = {...}, template = {...}, inputs = [dataset_uri]
2. Server: SearchSolutionsResponse // search_id = 057cf581-5d5e-48b2-8867-db72e7d1381d
3. Client: GetSearchSolutionsResults(GetSearchSolutionsResultsRequest) // search_id = 057cf581-5d5e-48b2-8867-db72e7d1381d
[SEARCH SOLUTIONS STREAM BEGINS]
4. Server: GetSearchSolutionsResultsResponse // progress = PENDING
5. Server: GetSearchSolutionsResultsResponse // progress = RUNNING, solution_id = 5b08f87a-8393-4fa4-95be-91a3e587fe54, internal_score = 0.6, done_ticks = 0.5, all_ticks = 1.0
6. Server: GetSearchSolutionsResultsResponse // progress = RUNNING, solution_id = 95de692f-ea81-4e7a-bef3-c01f18281bc0, internal_score = 0.8, done_ticks = 1.0, all_ticks = 1.0
7. Server: GetSearchSolutionsResultsResponse // progress = COMPLETED
[SEARCH SOLUTIONS STREAM ENDS]
8. Client: ScoreSolution(ScoreSolutionRequest) // solution_id = 95de692f-ea81-4e7a-bef3-c01f18281bc0, inputs = [dataset_uri], performance_metrics = [ACCURACY]
9. Server: ScoreSolutionResponse // request_id = 5d919354-4bd3-4155-9295-406d8c02b915
10. Client: GetScoreSolutionResults(GetScoreSolutionResultsRequest) // request_id = 5d919354-4bd3-4155-9295-406d8c02b915
[SCORE SOLUTION STREAM BEGINS]
11. Server: GetScoreSolutionResultsResponse // progress = PENDING
12. Server: GetScoreSolutionResultsResponse // progress = RUNNING
13. Server: GetScoreSolutionResultsResponse // progress = COMPLETED, scores = [0.9]
[SCORE SOLUTION STREAM END]
14. Client: EndSearchSolutions(EndSearchSolutionsRequest) // search_id = 057cf581-5d5e-48b2-8867-db72e7d1381d
15. Server: EndSearchSolutionsResponse
原语透传执行
以下是一个示例调用流程,其中TA3系统在一个数据集上调用一个原语并将转换后的数据集存储到Plasma存储中,它可以通过内存共享高效地访问它并向用户显示。即使原语只是一个转换且不需要拟合,TA3也必须在调用produce之前拟合一个解决方案。
此示例具有作为输入数据集和作为输出数据集的数据集。这与常规管道不同,常规管道以数据集作为输入并产生预测作为输出。原因是管道由TA3系统完全指定,因此输入和输出可以是任何东西。
1. Client: SearchSolutions(SearchSolutionsRequest) // problem = {...}, template = {...}, inputs = [dataset_uri]
2. Server: SearchSolutionsResponse // search_id = ae4de7f4-4435-4d86-834b-c183ef85f2d0
3. Client: GetSearchSolutionsResults(GetSearchSolutionsResultsRequest) // search_id = ae4de7f4-4435-4d86-834b-c183ef85f2d0
[SEARCH SOLUTIONS STREAM BEGINS]
4. Server: GetSearchSolutionsResultsResponse // progress = PENDING
5. Server: GetSearchSolutionsResultsResponse // progress = RUNNING, solution_id = 619e09ee-ccf5-4bd2-935d-41094169b0c5, internal_score = NaN, done_ticks = 1.0, all_ticks = 1.0
6. Server: GetSearchSolutionsResultsResponse // progress = COMPLETED
[SEARCH SOLUTIONS STREAM ENDS]
7. Client: FitSolution(FitSolutionRequest) // solution_id = 619e09ee-ccf5-4bd2-935d-41094169b0c5, inputs = [dataset_uri]
8. Server: FitSolutionResponse // request_id = e7fe4ef7-8b3a-4365-9fc4-c1a8228c509c
9. Client: GetFitSolutionResults(GetFitSolutionResultsRequest) // request_id = e7fe4ef7-8b3a-4365-9fc4-c1a8228c509c
[FIT SOLUTION STREAM BEGINS]
10. Server: GetFitSolutionResultsResponse // progress = PENDING
11. Server: GetFitSolutionResultsResponse // progress = RUNNING
12. Server: GetFitSolutionResultsResponse // progress = COMPLETED, fitted_solution_id = 88d627a4-e4ca-4b1a-9f2e-af9c54dfa860
[FIT SOLUTION STREAM END]
13. Client: ProduceSolution(ProduceSolutionRequest) // fitted_solution_id = 88d627a4-e4ca-4b1a-9f2e-af9c54dfa860, inputs = [dataset_uri], expose_outputs = ["outputs.0"], expose_value_types = [PLASMA_ID]
14. Server: ProduceSolutionResponse // request_id = 954b19cc-13d4-4c2a-a98f-8c15498014ac
15. Client: GetProduceSolutionResults(GetProduceSolutionResultsRequest) // request_id = 954b19cc-13d4-4c2a-a98f-8c15498014ac
[PRODUCE SOLUTION STREAM BEGINS]
16. Server: GetProduceSolutionResultsResponse // progress = PENDING
17. Server: GetProduceSolutionResultsResponse // progress = RUNNING, steps = [progress = PENDING]
18. Server: GetProduceSolutionResultsResponse // progress = RUNNING, steps = [progress = RUNNING]
19. Server: GetProduceSolutionResultsResponse // progress = RUNNING, steps = [progress = COMPLETED]
20. Server: GetProduceSolutionResultsResponse // progress = COMPLETED, steps = [progress = COMPLETED], exposed_outputs = {"outputs.0": ObjectID(6811fc1154520d677d58b01a51b47036d5a408a8)}
[PRODUCE SOLUTION STREAM END]
21. Client: EndSearchSolutions(EndSearchSolutionsRequest) // search_id = ae4de7f4-4435-4d86-834b-c183ef85f2d0
22. Server: EndSearchSolutionsResponse
上面使用的template
可能看起来像这样(消息以JSON格式显示)
{
"inputs": [
{
"name": "dataset"
}
],
"outputs": [
{
"name": "dataset",
"data": "step.0.produce"
}
],
"steps": [
{
"primitive": {
"id": "f5c2f905-b694-4cf9-b8c3-7cd7cf8d6acf"
},
"arguments": {
"inputs": {
"data": "inputs.0"
}
},
"outputs": [
{
"id": "produce"
}
]
}
]
}
标准端口
TA2-TA3 API的标准端口,TA2应在此端口上监听来自TA3的连接,端口为45042。
协议版本
为了支持更简单的调试,SearchSolutionsRequest
和SearchSolutionsResponse
消息包含各方使用的协议版本。这有助于通过检测版本不匹配来更容易地理解潜在的问题。
为了使其工作,version
字段必须从协议规范本身存储的值中填充。我们为此使用自定义选项。要从协议规范中检索版本,您可以在Python中执行以下操作
import core_pb2
version = core_pb2.DESCRIPTOR.GetOptions().Extensions[core_pb2.protocol_version]
在Go中,访问版本稍微复杂一些,请在此处描述。
消息扩展
GRPC和Protocol Buffers支持扩展消息的简单方法:只需在您的本地协议版本中定义带有自定义标记的额外字段。使用此协议的用户可以这样做来实验协议的变体(如果更改有效,他们可以提交合并请求以将更改包含到本规范中)。为了确保消息中此类非官方字段在执行者之间不冲突,请使用您组织的分配的标记范围,或通过合并请求添加您的组织。
更改日志
有关API更改的摘要,请参阅HISTORY.md。
仓库结构
master
分支包含TA3-TA2 API规范的最新稳定版本。devel
分支是下一版本的预发布分支。
版本通过标记。
在向master
和devel
分支提交的每个提交中,我们编译.proto
文件并将编译文件推送到用于多种语言的dist-*
和dev-dist-*
分支。您可以直接在项目中使用这些分支,使用git submodule
或类似机制。
贡献
有关如何为API开发做出贡献的更多信息,请参阅贡献指南。
关于数据驱动发现计划
DARPA数据驱动发现(D3M)计划正在研究让机器自动构建机器学习管道的方法。它分为三层:TA1(原语)、TA2(将原语自动组合成管道并执行它们的系统)和TA3(最终用户界面)。