M/模块

BigQuant 将复杂的算法和逻辑代码封装为简单易用的模块。模块支持一致的命名约定、版本控制和缓存/增量计算等功能。

我们将开放模块平台,用户可以开发自己的模块,在平台上使用、分享并获得收益。

设计原理

命名规则

模块的命名遵循如下规则:

M.模块名.v版本号(参数1=值1, 参数2=值2, ..)

版本管理

  • 模块支持版本管理,新版本发布后,旧版本仍然可以工作
  • 一个版本发布后,除了特别严重的bug,将不再修改。新功能将在新的版本上发布
  • 除非特殊情况,建议尽量使用最新模块的最新版本,版本不一定向后兼容,升级到新版的时候,可能需要对代码做一些改动

缓存/增量计算

  • 模块默认支持缓存功能 (部分模块根据需要显式的关闭了缓存)
  • 缓存key根据模块名、版本号和输入参数生成
    • 如果输入参数函数,建议函数需要用的局部变量都通过参数传入,不推荐使用全局变量,否则 在只是全局变量值更新时,模块仍然返回旧的缓存数据
    • 如果一定要在函数参数中使用全局变量,请将用到的全局变量放到 m_deps 参数中,具体见 Meta参数 部分

获取帮助

  • M.模块名.m_get_version:获取指定模块的所有版本
  • M.模块名.v版本号:接着按下快捷键Shift + Tab可以弹出该模块版本的帮助信息
  • 更多见 查看模块

Meta参数

meta参数可以用来控制模块的一些功能,使用方法见 使用模块

  • m_cached: 禁用缓存
  • m_deps: 额外的依赖,主要用于缓存key生成
  • m_silent: 是否输出meta logs

示例代码

M
In [6]:
M
Out[6]:

BigQuant模块入口。

    模块调用方式:M.模块名.v版本号(参数1=值1, 参数2=值2, ..)
    示例代码:M.filter.v2(data=some_ds, expr='date > "2017-01-01"')

    帮助文档:`模块和API概览 <https://bigquant.com/docs/module_and_api_overview.html>`_
查看模块
In [7]:
M.hellomodule
Out[7]:
模块:hellomodule
可用版本(推荐使用最新版本):v1
In [8]:
# 查看模块可用版本
M.hellomodule.m_get_version
Out[8]:
<bound method BigQuantModule.m_get_version of 模块:hellomodule
可用版本(推荐使用最新版本):v1>
In [11]:
M.hellomodule.v1
# 若要查看模块帮助文档,按Shift+Tab即可
Out[11]:
M.hellomodule.v1(input_ds=, another_input_ds=, param1=, param2=, param3=, param5=, foo=, param7=, bar='[1, 2, 3, 4]', bar1='bigquant_run = [1, 2, 3]', bar2=None, bar3='', param6=True, strparam='some_default_value')
In [19]:
# 查看模块源代码 (部分模块已经开放了源代码)
print(M.hellomodule.v1.m_sourcecode)
import pandas as pd

from biglearning.module2.common.data import DataSource, Outputs
import biglearning.module2.common.interface as I


# 是否自动缓存结果
bigquant_cacheable = True

# 如果模块已经不推荐使用,设置这个值为推荐使用的版本或者模块名,比如 v2
# bigquant_deprecated = '请更新到 ${MODULE_NAME} 最新版本'
bigquant_deprecated = None

# 模块是否外部可见,对外的模块应该设置为True
bigquant_public = True

# 是否开源
bigquant_opensource = True
bigquant_author = 'AISaaS'

# 模块接口定义
bigquant_category = '示例模块'
bigquant_friendly_name = 'Hello AISaaS Module'
bigquant_doc_url = 'https://bigquant.com/docs/'


def bigquant_run(
    input_ds: I.port('一个数据输入'),                 # 使用python anotation定义输入端
    another_input_ds: I.port('另一个数据输入'),
    param1: I.int('没有限制的int参数'),            # 使用python anotation定义参数
    param2: I.int('一个int参数', 0, 100),
    param3: I.float('一个float参数', min=-100.21, max=10),
    param5: I.choice('choice参数', ['hello', 'world', 'bigquant']),
    foo: I.code('文本字段'),
    param7: I.bool('bool参数,无默认值'),
    bar: I.code('简单python对象', I.code_python) = '[1, 2, 3, 4]',
    bar1: I.code('另一个python对象', I.code_python, auto_complete_type='python') = 'bigquant_run = [1, 2, 3]',
    bar2: I.code('python函数', I.code_python, default='def bigquant_run(some_ds):\n    return Outputs(data=some_ds)', auto_complete_type='python') = None,
    bar3: I.code('自动完成', I.code_python, auto_complete_type='python,history_data_fields,feature_fields,bigexpr_functions') = '',
    param6: I.bool('bool参数') = True,
    strparam: I.str('str参数') = 'some_default_value') -> [
        I.port('一个输出数据', 'some_ds'),            # 使用python anotation定义输出端
        I.port('另一个输出数据', 'another_ds', True),  # 可选输出端
        # I.port('延迟运行,将当前模块打包,可以作为其他模块的输入,在其他模块里运行。启用需要勾选模块的 延迟运行 参数。', I.port_name_lazy_run),
    ]:
    '''
    这是一个示例模块,用来展示如何创建一个模块。您可以拷贝此模块并修改成你需要的模块。
    一个模块应该至少包括一个 bigquant_run 函数。
    '''
    # do something here ...
    df = pd.DataFrame({'a': [1, 2, 3, 4]})
    return Outputs(
        some_ds=DataSource.write_df(df),
        another_ds=DataSource.write_df(df),
    )


def bigquant_postrun(outputs):
    '''
    bigquant_postrun 后处理函数,可选。输入是主函数的输出,可以在这里对数据做处理,或者返回更友好的outputs数据格式。此函数输出不会被缓存。
    :param outputs: 输入数据
    :return: 返回后处理后的数据
    @opensource
    '''
    def read_some(self):
        return pd.read_hdf(self.some_ds.path, 'data')
    outputs.extend_methods(read_some=read_some)

    def plot_datatable(self, df, output="display"):
        from bigcharts.datatale import plot
        return plot(df, output)
    outputs.extend_methods(plot_datatable=plot_datatable)

    def plot_tabs(self, kvs, output="display"):
        from bigcharts.tabs import plot
        return plot(kvs, output)
    outputs.extend_methods(plot_tabs=plot_tabs)

    return outputs


if __name__ == '__main__':
    # 测试代码
    pass

使用模块
In [20]:
def foo1(name):
    print('hello, %s' % name)
    df = pd.DataFrame({'a': range(0, 10)})
    ds = DataSource.write_df(df)
    return Outputs(bar=ds)

# 第一次运行的时候,会执行foo
m1 = M.cached.v3(run=foo1, kwargs=dict(name='quant'))
[2017-11-14 14:40:30.604245] INFO: bigquant: cached.v3 开始运行..
hello, quant
[2017-11-14 14:40:30.616688] INFO: bigquant: cached.v3 运行完成[0.012489s].
In [22]:
# 使用全局变量

bar = '1234'

def foo2(name):
    print('hello, %s, %s' % (name, bar))
    df = pd.DataFrame({'a': range(0, 10)})
    ds = DataSource.write_df(df)
    return Outputs(bar=ds)

# 第一次运行的时候,会执行foo
m1 = M.cached.v3(run=foo2, kwargs=dict(name='quant'), m_deps=[bar])
[2017-11-14 14:41:06.361961] INFO: bigquant: cached.v3 开始运行..
hello, quant, 1234
[2017-11-14 14:41:06.374537] INFO: bigquant: cached.v3 运行完成[0.012595s].
In [23]:
# 禁用缓存,m_cached=False

# 第一次运行的时候,会执行foo
m1 = M.cached.v3(run=foo1, kwargs=dict(name='quant'), m_cached=False)
[2017-11-14 14:41:37.908605] INFO: bigquant: cached.v3 开始运行..
hello, quant
[2017-11-14 14:41:37.920558] INFO: bigquant: cached.v3 运行完成[0.011962s].