spring-ai-alibaba-graph/spring-ai-alibaba-graph-example/src/main/java/org/springframework/ai/tool/function/FunctionToolCallback.java [51:223]:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
public class FunctionToolCallback<I, O> implements ToolCallback {

	private static final Logger logger = LoggerFactory.getLogger(FunctionToolCallback.class);

	private static final ToolCallResultConverter DEFAULT_RESULT_CONVERTER = new DefaultToolCallResultConverter();

	private static final ToolMetadata DEFAULT_TOOL_METADATA = ToolMetadata.builder().build();

	private final ToolDefinition toolDefinition;

	private final ToolMetadata toolMetadata;

	private final Type toolInputType;

	private final BiFunction<I, ToolContext, O> toolFunction;

	private final ToolCallResultConverter toolCallResultConverter;

	public FunctionToolCallback(ToolDefinition toolDefinition, @Nullable ToolMetadata toolMetadata, Type toolInputType,
			BiFunction<I, ToolContext, O> toolFunction, @Nullable ToolCallResultConverter toolCallResultConverter) {
		Assert.notNull(toolDefinition, "toolDefinition cannot be null");
		Assert.notNull(toolInputType, "toolInputType cannot be null");
		Assert.notNull(toolFunction, "toolFunction cannot be null");
		this.toolDefinition = toolDefinition;
		this.toolMetadata = toolMetadata != null ? toolMetadata : DEFAULT_TOOL_METADATA;
		this.toolFunction = toolFunction;
		this.toolInputType = toolInputType;
		this.toolCallResultConverter = toolCallResultConverter != null ? toolCallResultConverter
				: DEFAULT_RESULT_CONVERTER;
	}

	@Override
	public ToolDefinition getToolDefinition() {
		return toolDefinition;
	}

	@Override
	public ToolMetadata getToolMetadata() {
		return toolMetadata;
	}

	@Override
	public String call(String toolInput) {
		return call(toolInput, null);
	}

	@Override
	public String call(String toolInput, @Nullable ToolContext toolContext) {
		Assert.hasText(toolInput, "toolInput cannot be null or empty");

		logger.debug("Starting execution of tool: {}", toolDefinition.name());

		// TODO, fix issue https://github.com/spring-projects/spring-ai/issues/2497
		I request;
		if (toolInputType == String.class) {
			request = (I) toolInput;
		}
		else {
			request = JsonParser.fromJson(toolInput, toolInputType);
		}
		O response = toolFunction.apply(request, toolContext);

		logger.debug("Successful execution of tool: {}", toolDefinition.name());

		return toolCallResultConverter.convert(response, null);
	}

	@Override
	public String toString() {
		return "FunctionToolCallback{" + "toolDefinition=" + toolDefinition + ", toolMetadata=" + toolMetadata + '}';
	}

	/**
	 * Build a {@link FunctionToolCallback} from a {@link BiFunction}.
	 */
	public static <I, O> Builder<I, O> builder(String name, BiFunction<I, ToolContext, O> function) {
		return new Builder<>(name, function);
	}

	/**
	 * Build a {@link FunctionToolCallback} from a {@link Function}.
	 */
	public static <I, O> Builder<I, O> builder(String name, Function<I, O> function) {
		Assert.notNull(function, "function cannot be null");
		return new Builder<>(name, (request, context) -> function.apply(request));
	}

	/**
	 * Build a {@link FunctionToolCallback} from a {@link Supplier}.
	 */
	public static <O> Builder<Void, O> builder(String name, Supplier<O> supplier) {
		Assert.notNull(supplier, "supplier cannot be null");
		Function<Void, O> function = input -> supplier.get();
		return builder(name, function).inputType(Void.class);
	}

	/**
	 * Build a {@link FunctionToolCallback} from a {@link Consumer}.
	 */
	public static <I> Builder<I, Void> builder(String name, Consumer<I> consumer) {
		Assert.notNull(consumer, "consumer cannot be null");
		Function<I, Void> function = (I input) -> {
			consumer.accept(input);
			return null;
		};
		return builder(name, function);
	}

	public static class Builder<I, O> {

		private String name;

		private String description;

		private String inputSchema;

		private Type inputType;

		private ToolMetadata toolMetadata;

		private BiFunction<I, ToolContext, O> toolFunction;

		private ToolCallResultConverter toolCallResultConverter;

		private Builder(String name, BiFunction<I, ToolContext, O> toolFunction) {
			Assert.hasText(name, "name cannot be null or empty");
			Assert.notNull(toolFunction, "toolFunction cannot be null");
			this.name = name;
			this.toolFunction = toolFunction;
		}

		public Builder<I, O> description(String description) {
			this.description = description;
			return this;
		}

		public Builder<I, O> inputSchema(String inputSchema) {
			this.inputSchema = inputSchema;
			return this;
		}

		public Builder<I, O> inputType(Type inputType) {
			this.inputType = inputType;
			return this;
		}

		public Builder<I, O> inputType(ParameterizedTypeReference<?> inputType) {
			Assert.notNull(inputType, "inputType cannot be null");
			this.inputType = inputType.getType();
			return this;
		}

		public Builder<I, O> toolMetadata(ToolMetadata toolMetadata) {
			this.toolMetadata = toolMetadata;
			return this;
		}

		public Builder<I, O> toolCallResultConverter(ToolCallResultConverter toolCallResultConverter) {
			this.toolCallResultConverter = toolCallResultConverter;
			return this;
		}

		public FunctionToolCallback<I, O> build() {
			Assert.notNull(inputType, "inputType cannot be null");
			var toolDefinition = ToolDefinition.builder()
				.name(name)
				.description(
						StringUtils.hasText(description) ? description : ToolUtils.getToolDescriptionFromName(name))
				.inputSchema(
						StringUtils.hasText(inputSchema) ? inputSchema : JsonSchemaGenerator.generateForType(inputType))
				.build();
			return new FunctionToolCallback<>(toolDefinition, toolMetadata, inputType, toolFunction,
					toolCallResultConverter);
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -



spring-ai-alibaba-jmanus/src/main/java/org/springframework/ai/tool/function/FunctionToolCallback.java [51:223]:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
public class FunctionToolCallback<I, O> implements ToolCallback {

	private static final Logger logger = LoggerFactory.getLogger(FunctionToolCallback.class);

	private static final ToolCallResultConverter DEFAULT_RESULT_CONVERTER = new DefaultToolCallResultConverter();

	private static final ToolMetadata DEFAULT_TOOL_METADATA = ToolMetadata.builder().build();

	private final ToolDefinition toolDefinition;

	private final ToolMetadata toolMetadata;

	private final Type toolInputType;

	private final BiFunction<I, ToolContext, O> toolFunction;

	private final ToolCallResultConverter toolCallResultConverter;

	public FunctionToolCallback(ToolDefinition toolDefinition, @Nullable ToolMetadata toolMetadata, Type toolInputType,
			BiFunction<I, ToolContext, O> toolFunction, @Nullable ToolCallResultConverter toolCallResultConverter) {
		Assert.notNull(toolDefinition, "toolDefinition cannot be null");
		Assert.notNull(toolInputType, "toolInputType cannot be null");
		Assert.notNull(toolFunction, "toolFunction cannot be null");
		this.toolDefinition = toolDefinition;
		this.toolMetadata = toolMetadata != null ? toolMetadata : DEFAULT_TOOL_METADATA;
		this.toolFunction = toolFunction;
		this.toolInputType = toolInputType;
		this.toolCallResultConverter = toolCallResultConverter != null ? toolCallResultConverter
				: DEFAULT_RESULT_CONVERTER;
	}

	@Override
	public ToolDefinition getToolDefinition() {
		return toolDefinition;
	}

	@Override
	public ToolMetadata getToolMetadata() {
		return toolMetadata;
	}

	@Override
	public String call(String toolInput) {
		return call(toolInput, null);
	}

	@Override
	public String call(String toolInput, @Nullable ToolContext toolContext) {
		Assert.hasText(toolInput, "toolInput cannot be null or empty");

		logger.debug("Starting execution of tool: {}", toolDefinition.name());

		// TODO, fix issue https://github.com/spring-projects/spring-ai/issues/2497
		I request;
		if (toolInputType == String.class) {
			request = (I) toolInput;
		}
		else {
			request = JsonParser.fromJson(toolInput, toolInputType);
		}
		O response = toolFunction.apply(request, toolContext);

		logger.debug("Successful execution of tool: {}", toolDefinition.name());

		return toolCallResultConverter.convert(response, null);
	}

	@Override
	public String toString() {
		return "FunctionToolCallback{" + "toolDefinition=" + toolDefinition + ", toolMetadata=" + toolMetadata + '}';
	}

	/**
	 * Build a {@link FunctionToolCallback} from a {@link BiFunction}.
	 */
	public static <I, O> Builder<I, O> builder(String name, BiFunction<I, ToolContext, O> function) {
		return new Builder<>(name, function);
	}

	/**
	 * Build a {@link FunctionToolCallback} from a {@link Function}.
	 */
	public static <I, O> Builder<I, O> builder(String name, Function<I, O> function) {
		Assert.notNull(function, "function cannot be null");
		return new Builder<>(name, (request, context) -> function.apply(request));
	}

	/**
	 * Build a {@link FunctionToolCallback} from a {@link Supplier}.
	 */
	public static <O> Builder<Void, O> builder(String name, Supplier<O> supplier) {
		Assert.notNull(supplier, "supplier cannot be null");
		Function<Void, O> function = input -> supplier.get();
		return builder(name, function).inputType(Void.class);
	}

	/**
	 * Build a {@link FunctionToolCallback} from a {@link Consumer}.
	 */
	public static <I> Builder<I, Void> builder(String name, Consumer<I> consumer) {
		Assert.notNull(consumer, "consumer cannot be null");
		Function<I, Void> function = (I input) -> {
			consumer.accept(input);
			return null;
		};
		return builder(name, function);
	}

	public static class Builder<I, O> {

		private String name;

		private String description;

		private String inputSchema;

		private Type inputType;

		private ToolMetadata toolMetadata;

		private BiFunction<I, ToolContext, O> toolFunction;

		private ToolCallResultConverter toolCallResultConverter;

		private Builder(String name, BiFunction<I, ToolContext, O> toolFunction) {
			Assert.hasText(name, "name cannot be null or empty");
			Assert.notNull(toolFunction, "toolFunction cannot be null");
			this.name = name;
			this.toolFunction = toolFunction;
		}

		public Builder<I, O> description(String description) {
			this.description = description;
			return this;
		}

		public Builder<I, O> inputSchema(String inputSchema) {
			this.inputSchema = inputSchema;
			return this;
		}

		public Builder<I, O> inputType(Type inputType) {
			this.inputType = inputType;
			return this;
		}

		public Builder<I, O> inputType(ParameterizedTypeReference<?> inputType) {
			Assert.notNull(inputType, "inputType cannot be null");
			this.inputType = inputType.getType();
			return this;
		}

		public Builder<I, O> toolMetadata(ToolMetadata toolMetadata) {
			this.toolMetadata = toolMetadata;
			return this;
		}

		public Builder<I, O> toolCallResultConverter(ToolCallResultConverter toolCallResultConverter) {
			this.toolCallResultConverter = toolCallResultConverter;
			return this;
		}

		public FunctionToolCallback<I, O> build() {
			Assert.notNull(inputType, "inputType cannot be null");
			var toolDefinition = ToolDefinition.builder()
				.name(name)
				.description(
						StringUtils.hasText(description) ? description : ToolUtils.getToolDescriptionFromName(name))
				.inputSchema(
						StringUtils.hasText(inputSchema) ? inputSchema : JsonSchemaGenerator.generateForType(inputType))
				.build();
			return new FunctionToolCallback<>(toolDefinition, toolMetadata, inputType, toolFunction,
					toolCallResultConverter);
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -



