您的功能请求是否与问题相关?请描述。
目前,只有Java的内置类型(boolean、byte、short、int、long、float、double、BigDecimal、BigInteger、String、Array和类似数组)作为工具或函数的参数得到支持。然而,为了方便起见,可能还需要自定义类型。
- 示例*:假设我正在开发数据库工具;每个工具都与特定的列类型一起工作。如果没有自定义类型,我将需要在每个工具的接口中反复指定数据库、表和列名。
class DatabaseToolkit {
@Tool
void listByDatetime(
@P("Database name, it can be ....")
String dbName,
@P("Table name, it can be ....")
String tableName,
@P("Column name, it can be ....")
String columnName,
long start, long end) {
// ...
}
@Tool
void listByMatch(
// bad: repeated definition and description
@P("Database name, it can be ....")
String dbName,
@P("Table name, it can be ....")
String tableName,
@P("Column name, it can be ....")
String columnName,
String pattern) {
// ...
}
// more repeated...
}
通过将这些名称组织在一个类似于Column的自定义类型中,我可以避免在每个工具或函数接口中重复它们。
class Column {
@P("Database name, it can be ....")
String dbName;
@P("Table name, it can be ....")
String tableName;
@P("Column name, it can be ....")
String columnName;
// ...
}
class DatabaseToolkit {
@Tool
void listByDatetime(
Column column,
long start, long end) {
// ...
}
@Tool
void listByMatch(
Column column,
String pattern) {
// ...
}
// more repeated...
}
此外,我可以通过使用Column示例列表一次操作多个列来实现这一点。如果没有自定义类型,实现这一功能将会很具挑战性。
描述您希望的解决方案
当前的实现通过 JsonSchema 描述了工具或函数接口,包括其所有参数,这是OpenAI doc的要求。Python LangChain是这样做的。遵循这一约定,我们可以在两个步骤中支持将自定义类型作为工具/函数参数:
- 构建一个JsonSchema生成器,将正确注解的自定义类型转换为JsonSchema;
- 构建一个JsonSchema验证器,将由LanguageModel生成的参数验证并强制转换为自定义类型。
要做到这一点,可以通过生成自定义类型的JsonSchema来扩展 ToolSpecifications 。为了将JsonSchema属性绑定到自定义类型及其字段上,可以引入新的注解,或者直接采用现有的注解,如 Jackson-Annotations 。在 DefaultToolExecutor 中,应添加代码以根据JsonSchema或相应的注解验证参数,然后将它们强制转换为相应的类型,包括自定义类型。
有几点需要考虑:
- 组合:当自定义类型派生时,应使用JsonSchema中的
allOf
属性递归地组合其超类的模式。 - 多态性:如果自定义类型是抽象的或者是可以接受其子类示例的超类,则应使用JsonSchema中的
oneOf
属性。 - 好处*:这种解决方案轻量级且对当前代码更改最少。它还避免了向langchain4j核心库添加额外的依赖项。
- 缺点*:可能会重蹈覆辙。
- 注意*:支持自定义类型参数将破坏 OpenAiTokenier 的令牌计数过程,因为该过程假定在估计工具规范中的令牌时参数只能是Java内置类型。一旦支持自定义类型,我们就应该更新OpenAiTokenizer的代码逻辑。
描述您考虑过的替代方案
由于Java中有许多开源的JsonSchema生成器,因此提出的解决方案可能是在重蹈覆辙。以下是几个替代方案:
- victools/jsonschema-generator 工具支持根据来自Jackson、Jakarta、javax和Swagger的注解生成和验证JsonSchema。
- networknt/json-schema-validator 工具支持基于Jackson的 JSON Schema Core Draft v4, v6, v7, v2019-09 and v2020-12 规范进行JSON模式验证。
- 好处*:采用这些现有方法的一个巨大好处是,一旦验证成功,您可以直接反序列化JSON字符串回bean,因为它们尊重像Jackson这样的序列化框架。
- 缺点*:然而,使用现有的JsonSchema生成器可能会向核心库引入更多的依赖项,而且它们的功能对于工具/函数调用情况可能过于广泛。
附加上下文
我的担忧包括:
- langchain4j真的需要自定义类型参数吗?
- 如果需要,是否有当前的过程来支持自定义类型参数?
- 如果不需要,首选的方法是在langchain4j中直接实现一个轻量级的JsonSchema(类似于初始解决方案)还是使用现有的JsonSchema生成器(如其他选项)?
3条答案
按热度按时间kmpatx3s1#
非常感谢!
一些想法:
@Tool
方法参数确实可以简化许多事情,但通常建议将模式展平以便于函数调用,因为LLM更容易遵循扁平模式而不是深嵌套模式。这可能在长期内不成立,所以仍然是一个很好的功能,但可能不是最高优先级。WDYT?
部分在#708中解决
与#859相关
djp7away2#
你好@langchain4j,
我想知道你链接的问题是否也涵盖了列表参数。目前我遇到了错误
array schema missing items ...
解决方法是告诉AI将值作为单个字符串中的逗号分隔列表传递。
shyt4zoc3#
非常感谢!
一些想法:
@Tool
方法参数来简化开发人员的事情是正确的,但通常建议将模式展平以便于LLM遵循扁平化模式,而不是深嵌套的模式。这可能在长期内不成立,因此仍然是一个很好的功能,但可能不是最高优先级。WDYT?
部分在#708中解决与#859相关
感谢您的出色工作!抱歉给您带来了延迟。我认为SPI解决方案非常好。我已经提交了一个PR,将
ToolSpecification
生成和ToolExecutionRequest
反序列化委托给ToolJsonSchemas
,并使用JsonSchemaService
实现了VictoolsJsonSchemaService
,该实现使用victools/jsonschema-generator提供了更完整的JSON模式功能。除了SPI之外,还可以通过AiServices#jsonSchemaService
为JsonSchemaService
提供实现。