像写Python一样写JSON | intc: 专为人类设计的Python Config管理工具

像python代码一样,写json config也有补全文档和跳转功能

我们在开发时经常使用JSON或其衍生格式对我们的python代码进行配置,但是这些JSON格式的配置既难写又难读,难写是因为不像python一样有补全很容易忘记参数名,难读是由于我们经常忘记参数的含义以及约束是什么。这些痛点现在都将被intc解决

intc是一个功能强大的智能config配置管理工具,它不仅为我们的配置文件提供模块继承、模块嵌套、参数引用、超参搜索,还支持基于lambda表达式的复杂参数动态计算等功能。

而intc的配套Language Server Protocol(intc-lsp)则让我们的编辑浏览体验更加丝滑,它将配置文件与python代码紧密联合,intc-lsp可以帮助你在书写和阅读intc文件时方便的获取python的语义信息,提供错误提示、参数补全、智能跳转和参数帮助文档展示的功能。

除了用于config,intc还可以直接作为dataclass使用,它可以将我们使用intc定义的dataclass转化为json schema用于如LLM的数据类型约束,还可以对如LLM返回值在内的json数据进行数据检查并生成错误提示用于LLM的迭代优化。

Intc基础用法

python 复制代码
from intc import (
    MISSING,            # MISSING是一个常量(在intc中的值为`???`)表示参数缺失,需要在实例化config时提供
    Base,               # 所有的intc dataclass 都继承该类(可以隐式继承)
    BoolField,          # 这些bool field
    DictField,          # dict field
    FloatField,         # ...
    IntField,
    AnyField,
    ListField,
    NestField,          # 嵌套field,相比dict可以提供更多的类型检查、智能补全等功能
    StrField,
    SubModule,
    cregister,          # cregister注册intc实例(支持二级命名, <module_type, module_name> ),用于实例的索引(通过<module_type, module_name>直接获取对应的model类,config中也会使用注册名来定位对应的model类
)


@cregister("model", "simple_cls")  # cregister将Model注册为intc类,`module_type`为`model`, `module_name`为`simple_cls`
class Model(Base):                 # 显式继承自Base,这里也可以不显式继承,register过程会自动执行这个过程,显式的继承可以提供更好的语义补全
    embedding_combine_method = StrField( # dataclass的属性定义
        value="concat",                  # 默认值
        options=["concat", "concat_linear"], # options 表示值必须是这几个里面的一个
        help="the combine method, just `concat` or use `linear` on the concated embedding",
    )
    embedding_size = IntField(
        value=MISSING, help="the sum of bert and glove embedding size" # 这里的default value为MISSING,需要在实例化时提供
    )
    active = StrField(
        value="relu",
        options=["relu", "tanh", "sigmoid", "none"],
        help="the activation function",
    )
    submodule = SubModule(   # 子模型,可以嵌套其他模型的定义,这里的子模型可以有多个,引用子模型需要用到这些子模型的注册名
        value={},
        suggestions=[        # suggestions 表示推荐的一些值, 对于代码阅读和intc-lsp的语义解析有帮助
            "embedding",
            "decode",
        ],
        help="submodules for basic model",
    )

@cregister("embedding", "bert")
class BertEmbedding:
    hidden_size = IntField(
        value=MISSING,
        minimum=1,
        help="the input/output/hidden size for bert, must >= 1",
    )
    dropout_rate = FloatField(
        value=0.0, minimum=0.0, maximum=1.0, help="the dropout rate for bert"  #
    )
....

// 文件 config/model.jsonc
{
    "@model@simple_cls": {  // 表明是对谁进行配置,格式为@module_type@module_name @model@simple_cls 对应被注册为这个名称的`Model`
        "active": "none",
        "embedding_size": "@$.@glove.hidden_size, @$.@bert.hidden_size @lambda x, y: x+y", // 这里的值为动态的lambda计算的,喊一声 embedding_size的值为@embedding@glove.hidden_size和@embedding@bert.hidden_size 的和, 关于lambda的语法请看本说明里面关于lambda的介绍
        "@embedding@glove": { // submodule, submodule 同样以@module_type@module_name作为标识
            "hidden_size": 300,
            "vocab_size": 5000
        },
        "@embedding@bert": {
            "hidden_size": 768
        }
    }
}

DataClass 转化为Json Schema

python 复制代码
import json

from intc import MISSING, Base, IntField, NestField, StrField, dataclass


@dataclass
class LLMOutput(Base):
    """The output of the LLM model"""

    user_name = StrField(value=MISSING, help="Name of the person")

    class Info:
        age = IntField(value=MISSING, minimum=1, maximum=150, help="Age of the person")
        blood_type = StrField(
            value=MISSING, options=["A", "B", "AB", "O"], help="Blood type"
        )

    user_info = NestField(value=Info, help="User information")
    lines = IntField(value=MISSING, help="Number of lines in the output")
print(json.dumps(LLMOutput._json_schema(), indent=4))

Output:

json 复制代码
{
    "properties": {
        "user_name": {
            "description": "Name of the person",
            "type": "string",
            "deprecated": false
        },
        "user_info": {
            "description": "User information",
            "type": "object",
            "properties": {
                "age": {
                    "description": "Age of the person",
                    "type": "integer",
                    "deprecated": false,
                    "minimum": 1,
                    "maximum": 150
                },
                "blood_type": {
                    "description": "Blood type",
                    "type": "string",
                    "enum": [
                        "A",
                        "B",
                        "AB",
                        "O"
                    ],
                    "deprecated": false
                }
            }
        }
    },
    "type": "object",
    "description": "The output of the LLM model",
    "$schema": "https://json-schema.org/draft/2020-12/schema"
}

编写Config时的LSP支持展示(这里展示使用VSCODE和neovim时的效果)

More

这里只是对这个项目进行简单的介绍,更详细的文档和用法请参考Github项目

Github INTC

这个项目花费了我好多个周末的时间,欢迎大家提Issue和PR,如果有帮助也希望能帮忙点一下Star 谢谢

相关推荐
博观而约取厚积而薄发8 分钟前
Pytest 从入门到精通,一篇就够(超详细实战教程)
python·测试工具·单元测试·自动化·pytest
imzed18 分钟前
使用 Playwright + Pytest 构建 Web UI 自动化测试框架
python·自动化·pytest
普通网友23 分钟前
pytest一些常见的插件
开发语言·python·pytest
时空系32 分钟前
Python 高性能高压缩打包器 —— 基于 JianPy 语义分析引擎
python
cndes1 小时前
给Miniconda换源,让包下载更迅速
开发语言·python
Metaphor6921 小时前
使用 Python 添加、隐藏和删除 PDF 图层
python·pdf·图层
丨白色风车丨1 小时前
【Python 计算机视觉】基于 Dlib+OpenCV 实现实时人眼疲劳检测(闭眼预警)
python·opencv·计算机视觉
嘘嘘出差2 小时前
Python 爬虫入门实战:爬取豆瓣电影 Top 250
开发语言·爬虫·python
爱写代码的倒霉蛋2 小时前
实现协程的三种方式
开发语言·python