像写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 谢谢

相关推荐
极梦网络无忧4 小时前
OpenClaw 基础使用说明(中文版)
python
codeJinger4 小时前
【Python】操作Excel文件
python·excel
XLYcmy4 小时前
一个针对医疗RAG系统的数据窃取攻击工具
python·网络安全·ai·llm·agent·rag·ai安全
Islucas5 小时前
Claude code入门保姆级教程
python·bash·claude
萝卜白菜。5 小时前
TongWeb7.0相同的类指明加载顺序
开发语言·python·pycharm
赵钰老师5 小时前
【ADCIRC】基于“python+”潮汐、风驱动循环、风暴潮等海洋水动力模拟实践技术应用
python·信息可视化·数据分析
爬山算法5 小时前
MongoDB(80)如何在MongoDB中使用多文档事务?
数据库·python·mongodb
YuanDaima20486 小时前
基于 LangChain 1.0 的检索增强生成(RAG)实战
人工智能·笔记·python·langchain·个人开发·langgraph
RopenYuan6 小时前
FastAPI -API Router的应用
前端·网络·python