Coverage Report

Created: 2026-10-12 17:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/exprs/function/ai/ai_functions.h
Line
Count
Source
1
// Licensed to the Apache Software Foundation (ASF) under one
2
// or more contributor license agreements.  See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership.  The ASF licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License.  You may obtain a copy of the License at
8
//
9
//   http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing,
12
// software distributed under the License is distributed on an
13
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
// KIND, either express or implied.  See the License for the
15
// specific language governing permissions and limitations
16
// under the License.
17
18
#pragma once
19
20
#include <gen_cpp/FrontendService.h>
21
#include <gen_cpp/PaloInternalService_types.h>
22
#include <glog/logging.h>
23
24
#include <algorithm>
25
#include <cstdlib>
26
#include <memory>
27
#include <string>
28
#include <type_traits>
29
#include <utility>
30
#include <vector>
31
32
#include "common/config.h"
33
#include "common/status.h"
34
#include "core/column/column_array.h"
35
#include "core/column/column_const.h"
36
#include "core/column/column_nullable.h"
37
#include "core/cow.h"
38
#include "core/data_type/data_type_array.h"
39
#include "core/data_type/data_type_nullable.h"
40
#include "core/data_type/data_type_number.h"
41
#include "core/data_type/define_primitive_type.h"
42
#include "core/data_type/primitive_type.h"
43
#include "exec/common/util.hpp"
44
#include "exprs/function/ai/ai_adapter.h"
45
#include "exprs/function/ai/ai_request_executor.h"
46
#include "exprs/function/function.h"
47
#include "runtime/query_context.h"
48
#include "runtime/runtime_state.h"
49
#include "util/string_util.h"
50
#include "util/threadpool.h"
51
52
namespace doris {
53
54
// Base class for AI-based functions
55
template <typename Derived>
56
class AIFunction : public IFunction {
57
public:
58
16
    std::string get_name() const override { return assert_cast<const Derived&>(*this).name; }
_ZNK5doris10AIFunctionINS_13FunctionEmbedEE8get_nameB5cxx11Ev
Line
Count
Source
58
1
    std::string get_name() const override { return assert_cast<const Derived&>(*this).name; }
_ZNK5doris10AIFunctionINS_16FunctionAIFilterEE8get_nameB5cxx11Ev
Line
Count
Source
58
6
    std::string get_name() const override { return assert_cast<const Derived&>(*this).name; }
_ZNK5doris10AIFunctionINS_20FunctionAIFixGrammarEE8get_nameB5cxx11Ev
Line
Count
Source
58
1
    std::string get_name() const override { return assert_cast<const Derived&>(*this).name; }
_ZNK5doris10AIFunctionINS_19FunctionAISentimentEE8get_nameB5cxx11Ev
Line
Count
Source
58
1
    std::string get_name() const override { return assert_cast<const Derived&>(*this).name; }
_ZNK5doris10AIFunctionINS_19FunctionAISummarizeEE8get_nameB5cxx11Ev
Line
Count
Source
58
1
    std::string get_name() const override { return assert_cast<const Derived&>(*this).name; }
_ZNK5doris10AIFunctionINS_18FunctionAIClassifyEE8get_nameB5cxx11Ev
Line
Count
Source
58
1
    std::string get_name() const override { return assert_cast<const Derived&>(*this).name; }
_ZNK5doris10AIFunctionINS_17FunctionAIExtractEE8get_nameB5cxx11Ev
Line
Count
Source
58
1
    std::string get_name() const override { return assert_cast<const Derived&>(*this).name; }
_ZNK5doris10AIFunctionINS_18FunctionAIGenerateEE8get_nameB5cxx11Ev
Line
Count
Source
58
1
    std::string get_name() const override { return assert_cast<const Derived&>(*this).name; }
_ZNK5doris10AIFunctionINS_14FunctionAIMaskEE8get_nameB5cxx11Ev
Line
Count
Source
58
1
    std::string get_name() const override { return assert_cast<const Derived&>(*this).name; }
_ZNK5doris10AIFunctionINS_20FunctionAISimilarityEE8get_nameB5cxx11Ev
Line
Count
Source
58
1
    std::string get_name() const override { return assert_cast<const Derived&>(*this).name; }
_ZNK5doris10AIFunctionINS_19FunctionAITranslateEE8get_nameB5cxx11Ev
Line
Count
Source
58
1
    std::string get_name() const override { return assert_cast<const Derived&>(*this).name; }
59
60
    // If the user doesn't provide the first arg, `resource_name`
61
    // FE will add the `resource_name` to the arguments list using the Session Variable.
62
    // So the value here should be the maximum number that the function can accept.
63
12
    size_t get_number_of_arguments() const override {
64
12
        return assert_cast<const Derived&>(*this).number_of_arguments;
65
12
    }
_ZNK5doris10AIFunctionINS_13FunctionEmbedEE23get_number_of_argumentsEv
Line
Count
Source
63
4
    size_t get_number_of_arguments() const override {
64
4
        return assert_cast<const Derived&>(*this).number_of_arguments;
65
4
    }
_ZNK5doris10AIFunctionINS_16FunctionAIFilterEE23get_number_of_argumentsEv
Line
Count
Source
63
1
    size_t get_number_of_arguments() const override {
64
1
        return assert_cast<const Derived&>(*this).number_of_arguments;
65
1
    }
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_20FunctionAIFixGrammarEE23get_number_of_argumentsEv
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_19FunctionAISentimentEE23get_number_of_argumentsEv
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_19FunctionAISummarizeEE23get_number_of_argumentsEv
_ZNK5doris10AIFunctionINS_18FunctionAIClassifyEE23get_number_of_argumentsEv
Line
Count
Source
63
2
    size_t get_number_of_arguments() const override {
64
2
        return assert_cast<const Derived&>(*this).number_of_arguments;
65
2
    }
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_17FunctionAIExtractEE23get_number_of_argumentsEv
_ZNK5doris10AIFunctionINS_18FunctionAIGenerateEE23get_number_of_argumentsEv
Line
Count
Source
63
4
    size_t get_number_of_arguments() const override {
64
4
        return assert_cast<const Derived&>(*this).number_of_arguments;
65
4
    }
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_14FunctionAIMaskEE23get_number_of_argumentsEv
_ZNK5doris10AIFunctionINS_20FunctionAISimilarityEE23get_number_of_argumentsEv
Line
Count
Source
63
1
    size_t get_number_of_arguments() const override {
64
1
        return assert_cast<const Derived&>(*this).number_of_arguments;
65
1
    }
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_19FunctionAITranslateEE23get_number_of_argumentsEv
66
67
0
    bool is_blockable() const override { return true; }
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_13FunctionEmbedEE12is_blockableEv
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_16FunctionAIFilterEE12is_blockableEv
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_20FunctionAIFixGrammarEE12is_blockableEv
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_19FunctionAISentimentEE12is_blockableEv
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_19FunctionAISummarizeEE12is_blockableEv
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_18FunctionAIClassifyEE12is_blockableEv
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_17FunctionAIExtractEE12is_blockableEv
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_18FunctionAIGenerateEE12is_blockableEv
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_14FunctionAIMaskEE12is_blockableEv
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_20FunctionAISimilarityEE12is_blockableEv
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_19FunctionAITranslateEE12is_blockableEv
68
69
1
    Status close(FunctionContext* context, FunctionContext::FunctionStateScope scope) override {
70
1
        if (scope == FunctionContext::THREAD_LOCAL) {
71
            // Release this execution context's cached clients.
72
1
            context->set_function_state(scope, nullptr);
73
1
        }
74
1
        return Status::OK();
75
1
    }
Unexecuted instantiation: _ZN5doris10AIFunctionINS_13FunctionEmbedEE5closeEPNS_15FunctionContextENS3_18FunctionStateScopeE
Unexecuted instantiation: _ZN5doris10AIFunctionINS_16FunctionAIFilterEE5closeEPNS_15FunctionContextENS3_18FunctionStateScopeE
Unexecuted instantiation: _ZN5doris10AIFunctionINS_20FunctionAIFixGrammarEE5closeEPNS_15FunctionContextENS3_18FunctionStateScopeE
Unexecuted instantiation: _ZN5doris10AIFunctionINS_19FunctionAISentimentEE5closeEPNS_15FunctionContextENS3_18FunctionStateScopeE
_ZN5doris10AIFunctionINS_19FunctionAISummarizeEE5closeEPNS_15FunctionContextENS3_18FunctionStateScopeE
Line
Count
Source
69
1
    Status close(FunctionContext* context, FunctionContext::FunctionStateScope scope) override {
70
1
        if (scope == FunctionContext::THREAD_LOCAL) {
71
            // Release this execution context's cached clients.
72
1
            context->set_function_state(scope, nullptr);
73
1
        }
74
1
        return Status::OK();
75
1
    }
Unexecuted instantiation: _ZN5doris10AIFunctionINS_18FunctionAIClassifyEE5closeEPNS_15FunctionContextENS3_18FunctionStateScopeE
Unexecuted instantiation: _ZN5doris10AIFunctionINS_17FunctionAIExtractEE5closeEPNS_15FunctionContextENS3_18FunctionStateScopeE
Unexecuted instantiation: _ZN5doris10AIFunctionINS_18FunctionAIGenerateEE5closeEPNS_15FunctionContextENS3_18FunctionStateScopeE
Unexecuted instantiation: _ZN5doris10AIFunctionINS_14FunctionAIMaskEE5closeEPNS_15FunctionContextENS3_18FunctionStateScopeE
Unexecuted instantiation: _ZN5doris10AIFunctionINS_20FunctionAISimilarityEE5closeEPNS_15FunctionContextENS3_18FunctionStateScopeE
Unexecuted instantiation: _ZN5doris10AIFunctionINS_19FunctionAITranslateEE5closeEPNS_15FunctionContextENS3_18FunctionStateScopeE
76
77
24
    bool use_default_implementation_for_nulls() const final { return false; }
_ZNK5doris10AIFunctionINS_13FunctionEmbedEE36use_default_implementation_for_nullsEv
Line
Count
Source
77
8
    bool use_default_implementation_for_nulls() const final { return false; }
_ZNK5doris10AIFunctionINS_16FunctionAIFilterEE36use_default_implementation_for_nullsEv
Line
Count
Source
77
2
    bool use_default_implementation_for_nulls() const final { return false; }
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_20FunctionAIFixGrammarEE36use_default_implementation_for_nullsEv
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_19FunctionAISentimentEE36use_default_implementation_for_nullsEv
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_19FunctionAISummarizeEE36use_default_implementation_for_nullsEv
_ZNK5doris10AIFunctionINS_18FunctionAIClassifyEE36use_default_implementation_for_nullsEv
Line
Count
Source
77
4
    bool use_default_implementation_for_nulls() const final { return false; }
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_17FunctionAIExtractEE36use_default_implementation_for_nullsEv
_ZNK5doris10AIFunctionINS_18FunctionAIGenerateEE36use_default_implementation_for_nullsEv
Line
Count
Source
77
8
    bool use_default_implementation_for_nulls() const final { return false; }
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_14FunctionAIMaskEE36use_default_implementation_for_nullsEv
_ZNK5doris10AIFunctionINS_20FunctionAISimilarityEE36use_default_implementation_for_nullsEv
Line
Count
Source
77
2
    bool use_default_implementation_for_nulls() const final { return false; }
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_19FunctionAITranslateEE36use_default_implementation_for_nullsEv
78
79
23
    DataTypePtr get_return_type_impl(const DataTypes& arguments) const final {
80
23
        bool has_nullable_argument = std::ranges::any_of(
81
25
                arguments, [](const auto& argument) { return argument->is_nullable(); });
_ZZNK5doris10AIFunctionINS_13FunctionEmbedEE20get_return_type_implERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS7_EEENKUlRKT_E_clIS7_EEDaSE_
Line
Count
Source
81
8
                arguments, [](const auto& argument) { return argument->is_nullable(); });
_ZZNK5doris10AIFunctionINS_16FunctionAIFilterEE20get_return_type_implERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS7_EEENKUlRKT_E_clIS7_EEDaSE_
Line
Count
Source
81
2
                arguments, [](const auto& argument) { return argument->is_nullable(); });
Unexecuted instantiation: _ZZNK5doris10AIFunctionINS_20FunctionAIFixGrammarEE20get_return_type_implERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS7_EEENKUlRKT_E_clIS7_EEDaSE_
Unexecuted instantiation: _ZZNK5doris10AIFunctionINS_19FunctionAISentimentEE20get_return_type_implERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS7_EEENKUlRKT_E_clIS7_EEDaSE_
Unexecuted instantiation: _ZZNK5doris10AIFunctionINS_19FunctionAISummarizeEE20get_return_type_implERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS7_EEENKUlRKT_E_clIS7_EEDaSE_
_ZZNK5doris10AIFunctionINS_18FunctionAIClassifyEE20get_return_type_implERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS7_EEENKUlRKT_E_clIS7_EEDaSE_
Line
Count
Source
81
6
                arguments, [](const auto& argument) { return argument->is_nullable(); });
Unexecuted instantiation: _ZZNK5doris10AIFunctionINS_17FunctionAIExtractEE20get_return_type_implERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS7_EEENKUlRKT_E_clIS7_EEDaSE_
_ZZNK5doris10AIFunctionINS_18FunctionAIGenerateEE20get_return_type_implERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS7_EEENKUlRKT_E_clIS7_EEDaSE_
Line
Count
Source
81
7
                arguments, [](const auto& argument) { return argument->is_nullable(); });
Unexecuted instantiation: _ZZNK5doris10AIFunctionINS_14FunctionAIMaskEE20get_return_type_implERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS7_EEENKUlRKT_E_clIS7_EEDaSE_
_ZZNK5doris10AIFunctionINS_20FunctionAISimilarityEE20get_return_type_implERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS7_EEENKUlRKT_E_clIS7_EEDaSE_
Line
Count
Source
81
2
                arguments, [](const auto& argument) { return argument->is_nullable(); });
Unexecuted instantiation: _ZZNK5doris10AIFunctionINS_19FunctionAITranslateEE20get_return_type_implERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS7_EEENKUlRKT_E_clIS7_EEDaSE_
82
23
        DataTypePtr return_type =
83
23
                assert_cast<const Derived&>(*this).get_nested_return_type_impl(arguments);
84
23
        return has_nullable_argument ? make_nullable(return_type) : return_type;
85
23
    }
_ZNK5doris10AIFunctionINS_13FunctionEmbedEE20get_return_type_implERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS7_EE
Line
Count
Source
79
5
    DataTypePtr get_return_type_impl(const DataTypes& arguments) const final {
80
5
        bool has_nullable_argument = std::ranges::any_of(
81
5
                arguments, [](const auto& argument) { return argument->is_nullable(); });
82
5
        DataTypePtr return_type =
83
5
                assert_cast<const Derived&>(*this).get_nested_return_type_impl(arguments);
84
5
        return has_nullable_argument ? make_nullable(return_type) : return_type;
85
5
    }
_ZNK5doris10AIFunctionINS_16FunctionAIFilterEE20get_return_type_implERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS7_EE
Line
Count
Source
79
2
    DataTypePtr get_return_type_impl(const DataTypes& arguments) const final {
80
2
        bool has_nullable_argument = std::ranges::any_of(
81
2
                arguments, [](const auto& argument) { return argument->is_nullable(); });
82
2
        DataTypePtr return_type =
83
2
                assert_cast<const Derived&>(*this).get_nested_return_type_impl(arguments);
84
2
        return has_nullable_argument ? make_nullable(return_type) : return_type;
85
2
    }
_ZNK5doris10AIFunctionINS_20FunctionAIFixGrammarEE20get_return_type_implERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS7_EE
Line
Count
Source
79
1
    DataTypePtr get_return_type_impl(const DataTypes& arguments) const final {
80
1
        bool has_nullable_argument = std::ranges::any_of(
81
1
                arguments, [](const auto& argument) { return argument->is_nullable(); });
82
1
        DataTypePtr return_type =
83
1
                assert_cast<const Derived&>(*this).get_nested_return_type_impl(arguments);
84
1
        return has_nullable_argument ? make_nullable(return_type) : return_type;
85
1
    }
_ZNK5doris10AIFunctionINS_19FunctionAISentimentEE20get_return_type_implERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS7_EE
Line
Count
Source
79
1
    DataTypePtr get_return_type_impl(const DataTypes& arguments) const final {
80
1
        bool has_nullable_argument = std::ranges::any_of(
81
1
                arguments, [](const auto& argument) { return argument->is_nullable(); });
82
1
        DataTypePtr return_type =
83
1
                assert_cast<const Derived&>(*this).get_nested_return_type_impl(arguments);
84
1
        return has_nullable_argument ? make_nullable(return_type) : return_type;
85
1
    }
_ZNK5doris10AIFunctionINS_19FunctionAISummarizeEE20get_return_type_implERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS7_EE
Line
Count
Source
79
1
    DataTypePtr get_return_type_impl(const DataTypes& arguments) const final {
80
1
        bool has_nullable_argument = std::ranges::any_of(
81
1
                arguments, [](const auto& argument) { return argument->is_nullable(); });
82
1
        DataTypePtr return_type =
83
1
                assert_cast<const Derived&>(*this).get_nested_return_type_impl(arguments);
84
1
        return has_nullable_argument ? make_nullable(return_type) : return_type;
85
1
    }
_ZNK5doris10AIFunctionINS_18FunctionAIClassifyEE20get_return_type_implERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS7_EE
Line
Count
Source
79
3
    DataTypePtr get_return_type_impl(const DataTypes& arguments) const final {
80
3
        bool has_nullable_argument = std::ranges::any_of(
81
3
                arguments, [](const auto& argument) { return argument->is_nullable(); });
82
3
        DataTypePtr return_type =
83
3
                assert_cast<const Derived&>(*this).get_nested_return_type_impl(arguments);
84
3
        return has_nullable_argument ? make_nullable(return_type) : return_type;
85
3
    }
_ZNK5doris10AIFunctionINS_17FunctionAIExtractEE20get_return_type_implERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS7_EE
Line
Count
Source
79
1
    DataTypePtr get_return_type_impl(const DataTypes& arguments) const final {
80
1
        bool has_nullable_argument = std::ranges::any_of(
81
1
                arguments, [](const auto& argument) { return argument->is_nullable(); });
82
1
        DataTypePtr return_type =
83
1
                assert_cast<const Derived&>(*this).get_nested_return_type_impl(arguments);
84
1
        return has_nullable_argument ? make_nullable(return_type) : return_type;
85
1
    }
_ZNK5doris10AIFunctionINS_18FunctionAIGenerateEE20get_return_type_implERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS7_EE
Line
Count
Source
79
5
    DataTypePtr get_return_type_impl(const DataTypes& arguments) const final {
80
5
        bool has_nullable_argument = std::ranges::any_of(
81
5
                arguments, [](const auto& argument) { return argument->is_nullable(); });
82
5
        DataTypePtr return_type =
83
5
                assert_cast<const Derived&>(*this).get_nested_return_type_impl(arguments);
84
5
        return has_nullable_argument ? make_nullable(return_type) : return_type;
85
5
    }
_ZNK5doris10AIFunctionINS_14FunctionAIMaskEE20get_return_type_implERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS7_EE
Line
Count
Source
79
1
    DataTypePtr get_return_type_impl(const DataTypes& arguments) const final {
80
1
        bool has_nullable_argument = std::ranges::any_of(
81
1
                arguments, [](const auto& argument) { return argument->is_nullable(); });
82
1
        DataTypePtr return_type =
83
1
                assert_cast<const Derived&>(*this).get_nested_return_type_impl(arguments);
84
1
        return has_nullable_argument ? make_nullable(return_type) : return_type;
85
1
    }
_ZNK5doris10AIFunctionINS_20FunctionAISimilarityEE20get_return_type_implERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS7_EE
Line
Count
Source
79
2
    DataTypePtr get_return_type_impl(const DataTypes& arguments) const final {
80
2
        bool has_nullable_argument = std::ranges::any_of(
81
2
                arguments, [](const auto& argument) { return argument->is_nullable(); });
82
2
        DataTypePtr return_type =
83
2
                assert_cast<const Derived&>(*this).get_nested_return_type_impl(arguments);
84
2
        return has_nullable_argument ? make_nullable(return_type) : return_type;
85
2
    }
_ZNK5doris10AIFunctionINS_19FunctionAITranslateEE20get_return_type_implERKSt6vectorISt10shared_ptrIKNS_9IDataTypeEESaIS7_EE
Line
Count
Source
79
1
    DataTypePtr get_return_type_impl(const DataTypes& arguments) const final {
80
1
        bool has_nullable_argument = std::ranges::any_of(
81
1
                arguments, [](const auto& argument) { return argument->is_nullable(); });
82
1
        DataTypePtr return_type =
83
1
                assert_cast<const Derived&>(*this).get_nested_return_type_impl(arguments);
84
1
        return has_nullable_argument ? make_nullable(return_type) : return_type;
85
1
    }
86
87
    using PreparedFunctionImpl::execute;
88
89
    virtual Status build_prompt(const Columns& prompt_columns, size_t row_num,
90
107
                                std::string& prompt) const {
91
107
        StringRef text_ref = prompt_columns[0]->get_data_at(row_num);
92
107
        prompt = std::string(text_ref.data, text_ref.size);
93
94
107
        return Status::OK();
95
107
    }
_ZNK5doris10AIFunctionINS_13FunctionEmbedEE12build_promptERKSt6vectorINS_3COWINS_7IColumnEE13immutable_ptrIS5_EESaIS8_EEmRNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
Line
Count
Source
90
25
                                std::string& prompt) const {
91
25
        StringRef text_ref = prompt_columns[0]->get_data_at(row_num);
92
25
        prompt = std::string(text_ref.data, text_ref.size);
93
94
25
        return Status::OK();
95
25
    }
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_18FunctionAIClassifyEE12build_promptERKSt6vectorINS_3COWINS_7IColumnEE13immutable_ptrIS5_EESaIS8_EEmRNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_17FunctionAIExtractEE12build_promptERKSt6vectorINS_3COWINS_7IColumnEE13immutable_ptrIS5_EESaIS8_EEmRNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
_ZNK5doris10AIFunctionINS_16FunctionAIFilterEE12build_promptERKSt6vectorINS_3COWINS_7IColumnEE13immutable_ptrIS5_EESaIS8_EEmRNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
Line
Count
Source
90
65
                                std::string& prompt) const {
91
65
        StringRef text_ref = prompt_columns[0]->get_data_at(row_num);
92
65
        prompt = std::string(text_ref.data, text_ref.size);
93
94
65
        return Status::OK();
95
65
    }
_ZNK5doris10AIFunctionINS_20FunctionAIFixGrammarEE12build_promptERKSt6vectorINS_3COWINS_7IColumnEE13immutable_ptrIS5_EESaIS8_EEmRNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
Line
Count
Source
90
1
                                std::string& prompt) const {
91
1
        StringRef text_ref = prompt_columns[0]->get_data_at(row_num);
92
1
        prompt = std::string(text_ref.data, text_ref.size);
93
94
1
        return Status::OK();
95
1
    }
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_18FunctionAIGenerateEE12build_promptERKSt6vectorINS_3COWINS_7IColumnEE13immutable_ptrIS5_EESaIS8_EEmRNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_14FunctionAIMaskEE12build_promptERKSt6vectorINS_3COWINS_7IColumnEE13immutable_ptrIS5_EESaIS8_EEmRNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
_ZNK5doris10AIFunctionINS_19FunctionAISentimentEE12build_promptERKSt6vectorINS_3COWINS_7IColumnEE13immutable_ptrIS5_EESaIS8_EEmRNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
Line
Count
Source
90
5
                                std::string& prompt) const {
91
5
        StringRef text_ref = prompt_columns[0]->get_data_at(row_num);
92
5
        prompt = std::string(text_ref.data, text_ref.size);
93
94
5
        return Status::OK();
95
5
    }
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_20FunctionAISimilarityEE12build_promptERKSt6vectorINS_3COWINS_7IColumnEE13immutable_ptrIS5_EESaIS8_EEmRNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
_ZNK5doris10AIFunctionINS_19FunctionAISummarizeEE12build_promptERKSt6vectorINS_3COWINS_7IColumnEE13immutable_ptrIS5_EESaIS8_EEmRNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
Line
Count
Source
90
11
                                std::string& prompt) const {
91
11
        StringRef text_ref = prompt_columns[0]->get_data_at(row_num);
92
11
        prompt = std::string(text_ref.data, text_ref.size);
93
94
11
        return Status::OK();
95
11
    }
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_19FunctionAITranslateEE12build_promptERKSt6vectorINS_3COWINS_7IColumnEE13immutable_ptrIS5_EESaIS8_EEmRNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
96
97
    Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
98
92
                        uint32_t result, size_t input_rows_count) const override {
99
92
        if (block.get_by_position(arguments[0]).column->only_null()) {
100
1
            block.get_by_position(result).column =
101
1
                    block.get_by_position(result).type->create_column_const(input_rows_count,
102
1
                                                                            Field());
103
1
            return Status::OK();
104
1
        }
105
106
91
        AIResource config;
107
91
        std::shared_ptr<AIAdapter> adapter;
108
91
        if (Status status = this->_init_from_resource(context, block, arguments, config, adapter);
109
91
            !status.ok()) {
110
0
            return status;
111
0
        }
112
113
91
        return assert_cast<const Derived&>(*this).execute(context, block, arguments, result,
114
91
                                                          input_rows_count, config, adapter);
115
91
    }
_ZNK5doris10AIFunctionINS_13FunctionEmbedEE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjm
Line
Count
Source
98
15
                        uint32_t result, size_t input_rows_count) const override {
99
15
        if (block.get_by_position(arguments[0]).column->only_null()) {
100
0
            block.get_by_position(result).column =
101
0
                    block.get_by_position(result).type->create_column_const(input_rows_count,
102
0
                                                                            Field());
103
0
            return Status::OK();
104
0
        }
105
106
15
        AIResource config;
107
15
        std::shared_ptr<AIAdapter> adapter;
108
15
        if (Status status = this->_init_from_resource(context, block, arguments, config, adapter);
109
15
            !status.ok()) {
110
0
            return status;
111
0
        }
112
113
15
        return assert_cast<const Derived&>(*this).execute(context, block, arguments, result,
114
15
                                                          input_rows_count, config, adapter);
115
15
    }
_ZNK5doris10AIFunctionINS_16FunctionAIFilterEE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjm
Line
Count
Source
98
47
                        uint32_t result, size_t input_rows_count) const override {
99
47
        if (block.get_by_position(arguments[0]).column->only_null()) {
100
0
            block.get_by_position(result).column =
101
0
                    block.get_by_position(result).type->create_column_const(input_rows_count,
102
0
                                                                            Field());
103
0
            return Status::OK();
104
0
        }
105
106
47
        AIResource config;
107
47
        std::shared_ptr<AIAdapter> adapter;
108
47
        if (Status status = this->_init_from_resource(context, block, arguments, config, adapter);
109
47
            !status.ok()) {
110
0
            return status;
111
0
        }
112
113
47
        return assert_cast<const Derived&>(*this).execute(context, block, arguments, result,
114
47
                                                          input_rows_count, config, adapter);
115
47
    }
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_20FunctionAIFixGrammarEE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjm
_ZNK5doris10AIFunctionINS_19FunctionAISentimentEE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjm
Line
Count
Source
98
2
                        uint32_t result, size_t input_rows_count) const override {
99
2
        if (block.get_by_position(arguments[0]).column->only_null()) {
100
0
            block.get_by_position(result).column =
101
0
                    block.get_by_position(result).type->create_column_const(input_rows_count,
102
0
                                                                            Field());
103
0
            return Status::OK();
104
0
        }
105
106
2
        AIResource config;
107
2
        std::shared_ptr<AIAdapter> adapter;
108
2
        if (Status status = this->_init_from_resource(context, block, arguments, config, adapter);
109
2
            !status.ok()) {
110
0
            return status;
111
0
        }
112
113
2
        return assert_cast<const Derived&>(*this).execute(context, block, arguments, result,
114
2
                                                          input_rows_count, config, adapter);
115
2
    }
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_19FunctionAISummarizeEE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjm
_ZNK5doris10AIFunctionINS_18FunctionAIClassifyEE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjm
Line
Count
Source
98
2
                        uint32_t result, size_t input_rows_count) const override {
99
2
        if (block.get_by_position(arguments[0]).column->only_null()) {
100
0
            block.get_by_position(result).column =
101
0
                    block.get_by_position(result).type->create_column_const(input_rows_count,
102
0
                                                                            Field());
103
0
            return Status::OK();
104
0
        }
105
106
2
        AIResource config;
107
2
        std::shared_ptr<AIAdapter> adapter;
108
2
        if (Status status = this->_init_from_resource(context, block, arguments, config, adapter);
109
2
            !status.ok()) {
110
0
            return status;
111
0
        }
112
113
2
        return assert_cast<const Derived&>(*this).execute(context, block, arguments, result,
114
2
                                                          input_rows_count, config, adapter);
115
2
    }
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_17FunctionAIExtractEE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjm
_ZNK5doris10AIFunctionINS_18FunctionAIGenerateEE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjm
Line
Count
Source
98
4
                        uint32_t result, size_t input_rows_count) const override {
99
4
        if (block.get_by_position(arguments[0]).column->only_null()) {
100
1
            block.get_by_position(result).column =
101
1
                    block.get_by_position(result).type->create_column_const(input_rows_count,
102
1
                                                                            Field());
103
1
            return Status::OK();
104
1
        }
105
106
3
        AIResource config;
107
3
        std::shared_ptr<AIAdapter> adapter;
108
3
        if (Status status = this->_init_from_resource(context, block, arguments, config, adapter);
109
3
            !status.ok()) {
110
0
            return status;
111
0
        }
112
113
3
        return assert_cast<const Derived&>(*this).execute(context, block, arguments, result,
114
3
                                                          input_rows_count, config, adapter);
115
3
    }
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_14FunctionAIMaskEE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjm
_ZNK5doris10AIFunctionINS_20FunctionAISimilarityEE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjm
Line
Count
Source
98
22
                        uint32_t result, size_t input_rows_count) const override {
99
22
        if (block.get_by_position(arguments[0]).column->only_null()) {
100
0
            block.get_by_position(result).column =
101
0
                    block.get_by_position(result).type->create_column_const(input_rows_count,
102
0
                                                                            Field());
103
0
            return Status::OK();
104
0
        }
105
106
22
        AIResource config;
107
22
        std::shared_ptr<AIAdapter> adapter;
108
22
        if (Status status = this->_init_from_resource(context, block, arguments, config, adapter);
109
22
            !status.ok()) {
110
0
            return status;
111
0
        }
112
113
22
        return assert_cast<const Derived&>(*this).execute(context, block, arguments, result,
114
22
                                                          input_rows_count, config, adapter);
115
22
    }
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_19FunctionAITranslateEE12execute_implEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjm
116
117
protected:
118
    // Reads the shared AI context window size from query options. String AI batch functions and
119
    // ai_agg both use the same byte-based session variable so batching behavior stays consistent.
120
91
    static int64_t get_ai_context_window_size(FunctionContext* context) {
121
91
        DORIS_CHECK(context != nullptr);
122
91
        QueryContext* query_ctx = context->state()->get_query_ctx();
123
91
        DORIS_CHECK(query_ctx != nullptr);
124
125
91
        return query_ctx->query_options().ai_context_window_size;
126
91
    }
_ZN5doris10AIFunctionINS_13FunctionEmbedEE26get_ai_context_window_sizeEPNS_15FunctionContextE
Line
Count
Source
120
11
    static int64_t get_ai_context_window_size(FunctionContext* context) {
121
11
        DORIS_CHECK(context != nullptr);
122
11
        QueryContext* query_ctx = context->state()->get_query_ctx();
123
11
        DORIS_CHECK(query_ctx != nullptr);
124
125
11
        return query_ctx->query_options().ai_context_window_size;
126
11
    }
_ZN5doris10AIFunctionINS_16FunctionAIFilterEE26get_ai_context_window_sizeEPNS_15FunctionContextE
Line
Count
Source
120
47
    static int64_t get_ai_context_window_size(FunctionContext* context) {
121
47
        DORIS_CHECK(context != nullptr);
122
47
        QueryContext* query_ctx = context->state()->get_query_ctx();
123
47
        DORIS_CHECK(query_ctx != nullptr);
124
125
47
        return query_ctx->query_options().ai_context_window_size;
126
47
    }
Unexecuted instantiation: _ZN5doris10AIFunctionINS_20FunctionAIFixGrammarEE26get_ai_context_window_sizeEPNS_15FunctionContextE
_ZN5doris10AIFunctionINS_19FunctionAISentimentEE26get_ai_context_window_sizeEPNS_15FunctionContextE
Line
Count
Source
120
2
    static int64_t get_ai_context_window_size(FunctionContext* context) {
121
2
        DORIS_CHECK(context != nullptr);
122
2
        QueryContext* query_ctx = context->state()->get_query_ctx();
123
2
        DORIS_CHECK(query_ctx != nullptr);
124
125
2
        return query_ctx->query_options().ai_context_window_size;
126
2
    }
_ZN5doris10AIFunctionINS_19FunctionAISummarizeEE26get_ai_context_window_sizeEPNS_15FunctionContextE
Line
Count
Source
120
5
    static int64_t get_ai_context_window_size(FunctionContext* context) {
121
5
        DORIS_CHECK(context != nullptr);
122
5
        QueryContext* query_ctx = context->state()->get_query_ctx();
123
5
        DORIS_CHECK(query_ctx != nullptr);
124
125
5
        return query_ctx->query_options().ai_context_window_size;
126
5
    }
_ZN5doris10AIFunctionINS_18FunctionAIClassifyEE26get_ai_context_window_sizeEPNS_15FunctionContextE
Line
Count
Source
120
2
    static int64_t get_ai_context_window_size(FunctionContext* context) {
121
2
        DORIS_CHECK(context != nullptr);
122
2
        QueryContext* query_ctx = context->state()->get_query_ctx();
123
2
        DORIS_CHECK(query_ctx != nullptr);
124
125
2
        return query_ctx->query_options().ai_context_window_size;
126
2
    }
Unexecuted instantiation: _ZN5doris10AIFunctionINS_17FunctionAIExtractEE26get_ai_context_window_sizeEPNS_15FunctionContextE
_ZN5doris10AIFunctionINS_18FunctionAIGenerateEE26get_ai_context_window_sizeEPNS_15FunctionContextE
Line
Count
Source
120
2
    static int64_t get_ai_context_window_size(FunctionContext* context) {
121
2
        DORIS_CHECK(context != nullptr);
122
2
        QueryContext* query_ctx = context->state()->get_query_ctx();
123
2
        DORIS_CHECK(query_ctx != nullptr);
124
125
2
        return query_ctx->query_options().ai_context_window_size;
126
2
    }
Unexecuted instantiation: _ZN5doris10AIFunctionINS_14FunctionAIMaskEE26get_ai_context_window_sizeEPNS_15FunctionContextE
_ZN5doris10AIFunctionINS_20FunctionAISimilarityEE26get_ai_context_window_sizeEPNS_15FunctionContextE
Line
Count
Source
120
22
    static int64_t get_ai_context_window_size(FunctionContext* context) {
121
22
        DORIS_CHECK(context != nullptr);
122
22
        QueryContext* query_ctx = context->state()->get_query_ctx();
123
22
        DORIS_CHECK(query_ctx != nullptr);
124
125
22
        return query_ctx->query_options().ai_context_window_size;
126
22
    }
Unexecuted instantiation: _ZN5doris10AIFunctionINS_19FunctionAITranslateEE26get_ai_context_window_sizeEPNS_15FunctionContextE
127
128
11
    MutableColumnPtr create_result_column() const { return ColumnString::create(); }
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_20FunctionAIFixGrammarEE20create_result_columnEv
_ZNK5doris10AIFunctionINS_19FunctionAISentimentEE20create_result_columnEv
Line
Count
Source
128
2
    MutableColumnPtr create_result_column() const { return ColumnString::create(); }
_ZNK5doris10AIFunctionINS_19FunctionAISummarizeEE20create_result_columnEv
Line
Count
Source
128
5
    MutableColumnPtr create_result_column() const { return ColumnString::create(); }
_ZNK5doris10AIFunctionINS_18FunctionAIClassifyEE20create_result_columnEv
Line
Count
Source
128
2
    MutableColumnPtr create_result_column() const { return ColumnString::create(); }
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_17FunctionAIExtractEE20create_result_columnEv
_ZNK5doris10AIFunctionINS_18FunctionAIGenerateEE20create_result_columnEv
Line
Count
Source
128
2
    MutableColumnPtr create_result_column() const { return ColumnString::create(); }
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_14FunctionAIMaskEE20create_result_columnEv
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_19FunctionAITranslateEE20create_result_columnEv
129
130
    // Provider-reusable hook for AI functions(string) -> string.
131
    Status append_batch_results(const std::vector<std::string>& batch_results,
132
16
                                IColumn& col_result) const {
133
16
        auto& string_col = assert_cast<ColumnString&>(col_result);
134
21
        for (const auto& batch_result : batch_results) {
135
21
            string_col.insert_data(batch_result.data(), batch_result.size());
136
21
        }
137
16
        return Status::OK();
138
16
    }
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_20FunctionAIFixGrammarEE20append_batch_resultsERKSt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS9_EERNS_7IColumnE
_ZNK5doris10AIFunctionINS_19FunctionAISentimentEE20append_batch_resultsERKSt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS9_EERNS_7IColumnE
Line
Count
Source
132
2
                                IColumn& col_result) const {
133
2
        auto& string_col = assert_cast<ColumnString&>(col_result);
134
4
        for (const auto& batch_result : batch_results) {
135
4
            string_col.insert_data(batch_result.data(), batch_result.size());
136
4
        }
137
2
        return Status::OK();
138
2
    }
_ZNK5doris10AIFunctionINS_19FunctionAISummarizeEE20append_batch_resultsERKSt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS9_EERNS_7IColumnE
Line
Count
Source
132
10
                                IColumn& col_result) const {
133
10
        auto& string_col = assert_cast<ColumnString&>(col_result);
134
10
        for (const auto& batch_result : batch_results) {
135
10
            string_col.insert_data(batch_result.data(), batch_result.size());
136
10
        }
137
10
        return Status::OK();
138
10
    }
_ZNK5doris10AIFunctionINS_18FunctionAIClassifyEE20append_batch_resultsERKSt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS9_EERNS_7IColumnE
Line
Count
Source
132
2
                                IColumn& col_result) const {
133
2
        auto& string_col = assert_cast<ColumnString&>(col_result);
134
2
        for (const auto& batch_result : batch_results) {
135
2
            string_col.insert_data(batch_result.data(), batch_result.size());
136
2
        }
137
2
        return Status::OK();
138
2
    }
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_17FunctionAIExtractEE20append_batch_resultsERKSt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS9_EERNS_7IColumnE
_ZNK5doris10AIFunctionINS_18FunctionAIGenerateEE20append_batch_resultsERKSt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS9_EERNS_7IColumnE
Line
Count
Source
132
2
                                IColumn& col_result) const {
133
2
        auto& string_col = assert_cast<ColumnString&>(col_result);
134
5
        for (const auto& batch_result : batch_results) {
135
5
            string_col.insert_data(batch_result.data(), batch_result.size());
136
5
        }
137
2
        return Status::OK();
138
2
    }
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_14FunctionAIMaskEE20append_batch_resultsERKSt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS9_EERNS_7IColumnE
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_19FunctionAITranslateEE20append_batch_resultsERKSt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS9_EERNS_7IColumnE
139
140
98
    static void normalize_endpoint(AIResource& config) {
141
        // 1. If users configure only the version root like `.../v1` or `.../v1beta`, append
142
        //    `models/<model>:batchEmbedContents` for `embed`, and `models/<model>:generateContent`
143
        //    for other AI scalar functions.
144
        // 2. `:embedContent` -> `:batchEmbedContents`
145
98
        if (iequal(config.provider_type, "GEMINI")) {
146
4
            if (iequal(Derived::name, "embed") && config.endpoint.ends_with(":embedContent")) {
147
1
                static constexpr std::string_view legacy_suffix = ":embedContent";
148
1
                config.endpoint.replace(config.endpoint.size() - legacy_suffix.size(),
149
1
                                        legacy_suffix.size(), ":batchEmbedContents");
150
1
                return;
151
1
            }
152
153
3
            if (!config.endpoint.ends_with("v1") && !config.endpoint.ends_with("v1beta")) {
154
1
                return;
155
1
            }
156
157
2
            std::string model_name = config.model_name;
158
2
            if (!model_name.starts_with("models/")) {
159
2
                model_name = "models/" + model_name;
160
2
            }
161
162
2
            config.endpoint += "/";
163
2
            config.endpoint += model_name;
164
2
            config.endpoint +=
165
2
                    iequal(Derived::name, "embed") ? ":batchEmbedContents" : ":generateContent";
166
2
            return;
167
3
        }
168
169
        // The endpoint `v1/completions` does not support `system_prompt`.
170
        // To ensure a clear structure and stable AI results.
171
        // Convert from `v1/completions` to `v1/chat/completions`
172
94
        if (config.endpoint.ends_with("v1/completions")) {
173
1
            static constexpr std::string_view legacy_suffix = "v1/completions";
174
1
            config.endpoint.replace(config.endpoint.size() - legacy_suffix.size(),
175
1
                                    legacy_suffix.size(), "v1/chat/completions");
176
1
        }
177
94
    }
_ZN5doris10AIFunctionINS_13FunctionEmbedEE18normalize_endpointERNS_10AIResourceE
Line
Count
Source
140
17
    static void normalize_endpoint(AIResource& config) {
141
        // 1. If users configure only the version root like `.../v1` or `.../v1beta`, append
142
        //    `models/<model>:batchEmbedContents` for `embed`, and `models/<model>:generateContent`
143
        //    for other AI scalar functions.
144
        // 2. `:embedContent` -> `:batchEmbedContents`
145
17
        if (iequal(config.provider_type, "GEMINI")) {
146
2
            if (iequal(Derived::name, "embed") && config.endpoint.ends_with(":embedContent")) {
147
1
                static constexpr std::string_view legacy_suffix = ":embedContent";
148
1
                config.endpoint.replace(config.endpoint.size() - legacy_suffix.size(),
149
1
                                        legacy_suffix.size(), ":batchEmbedContents");
150
1
                return;
151
1
            }
152
153
1
            if (!config.endpoint.ends_with("v1") && !config.endpoint.ends_with("v1beta")) {
154
0
                return;
155
0
            }
156
157
1
            std::string model_name = config.model_name;
158
1
            if (!model_name.starts_with("models/")) {
159
1
                model_name = "models/" + model_name;
160
1
            }
161
162
1
            config.endpoint += "/";
163
1
            config.endpoint += model_name;
164
1
            config.endpoint +=
165
1
                    iequal(Derived::name, "embed") ? ":batchEmbedContents" : ":generateContent";
166
1
            return;
167
1
        }
168
169
        // The endpoint `v1/completions` does not support `system_prompt`.
170
        // To ensure a clear structure and stable AI results.
171
        // Convert from `v1/completions` to `v1/chat/completions`
172
15
        if (config.endpoint.ends_with("v1/completions")) {
173
0
            static constexpr std::string_view legacy_suffix = "v1/completions";
174
0
            config.endpoint.replace(config.endpoint.size() - legacy_suffix.size(),
175
0
                                    legacy_suffix.size(), "v1/chat/completions");
176
0
        }
177
15
    }
_ZN5doris10AIFunctionINS_16FunctionAIFilterEE18normalize_endpointERNS_10AIResourceE
Line
Count
Source
140
47
    static void normalize_endpoint(AIResource& config) {
141
        // 1. If users configure only the version root like `.../v1` or `.../v1beta`, append
142
        //    `models/<model>:batchEmbedContents` for `embed`, and `models/<model>:generateContent`
143
        //    for other AI scalar functions.
144
        // 2. `:embedContent` -> `:batchEmbedContents`
145
47
        if (iequal(config.provider_type, "GEMINI")) {
146
0
            if (iequal(Derived::name, "embed") && config.endpoint.ends_with(":embedContent")) {
147
0
                static constexpr std::string_view legacy_suffix = ":embedContent";
148
0
                config.endpoint.replace(config.endpoint.size() - legacy_suffix.size(),
149
0
                                        legacy_suffix.size(), ":batchEmbedContents");
150
0
                return;
151
0
            }
152
153
0
            if (!config.endpoint.ends_with("v1") && !config.endpoint.ends_with("v1beta")) {
154
0
                return;
155
0
            }
156
157
0
            std::string model_name = config.model_name;
158
0
            if (!model_name.starts_with("models/")) {
159
0
                model_name = "models/" + model_name;
160
0
            }
161
162
0
            config.endpoint += "/";
163
0
            config.endpoint += model_name;
164
0
            config.endpoint +=
165
0
                    iequal(Derived::name, "embed") ? ":batchEmbedContents" : ":generateContent";
166
0
            return;
167
0
        }
168
169
        // The endpoint `v1/completions` does not support `system_prompt`.
170
        // To ensure a clear structure and stable AI results.
171
        // Convert from `v1/completions` to `v1/chat/completions`
172
47
        if (config.endpoint.ends_with("v1/completions")) {
173
0
            static constexpr std::string_view legacy_suffix = "v1/completions";
174
0
            config.endpoint.replace(config.endpoint.size() - legacy_suffix.size(),
175
0
                                    legacy_suffix.size(), "v1/chat/completions");
176
0
        }
177
47
    }
Unexecuted instantiation: _ZN5doris10AIFunctionINS_20FunctionAIFixGrammarEE18normalize_endpointERNS_10AIResourceE
_ZN5doris10AIFunctionINS_19FunctionAISentimentEE18normalize_endpointERNS_10AIResourceE
Line
Count
Source
140
7
    static void normalize_endpoint(AIResource& config) {
141
        // 1. If users configure only the version root like `.../v1` or `.../v1beta`, append
142
        //    `models/<model>:batchEmbedContents` for `embed`, and `models/<model>:generateContent`
143
        //    for other AI scalar functions.
144
        // 2. `:embedContent` -> `:batchEmbedContents`
145
7
        if (iequal(config.provider_type, "GEMINI")) {
146
2
            if (iequal(Derived::name, "embed") && config.endpoint.ends_with(":embedContent")) {
147
0
                static constexpr std::string_view legacy_suffix = ":embedContent";
148
0
                config.endpoint.replace(config.endpoint.size() - legacy_suffix.size(),
149
0
                                        legacy_suffix.size(), ":batchEmbedContents");
150
0
                return;
151
0
            }
152
153
2
            if (!config.endpoint.ends_with("v1") && !config.endpoint.ends_with("v1beta")) {
154
1
                return;
155
1
            }
156
157
1
            std::string model_name = config.model_name;
158
1
            if (!model_name.starts_with("models/")) {
159
1
                model_name = "models/" + model_name;
160
1
            }
161
162
1
            config.endpoint += "/";
163
1
            config.endpoint += model_name;
164
1
            config.endpoint +=
165
1
                    iequal(Derived::name, "embed") ? ":batchEmbedContents" : ":generateContent";
166
1
            return;
167
2
        }
168
169
        // The endpoint `v1/completions` does not support `system_prompt`.
170
        // To ensure a clear structure and stable AI results.
171
        // Convert from `v1/completions` to `v1/chat/completions`
172
5
        if (config.endpoint.ends_with("v1/completions")) {
173
1
            static constexpr std::string_view legacy_suffix = "v1/completions";
174
1
            config.endpoint.replace(config.endpoint.size() - legacy_suffix.size(),
175
1
                                    legacy_suffix.size(), "v1/chat/completions");
176
1
        }
177
5
    }
Unexecuted instantiation: _ZN5doris10AIFunctionINS_19FunctionAISummarizeEE18normalize_endpointERNS_10AIResourceE
_ZN5doris10AIFunctionINS_18FunctionAIClassifyEE18normalize_endpointERNS_10AIResourceE
Line
Count
Source
140
2
    static void normalize_endpoint(AIResource& config) {
141
        // 1. If users configure only the version root like `.../v1` or `.../v1beta`, append
142
        //    `models/<model>:batchEmbedContents` for `embed`, and `models/<model>:generateContent`
143
        //    for other AI scalar functions.
144
        // 2. `:embedContent` -> `:batchEmbedContents`
145
2
        if (iequal(config.provider_type, "GEMINI")) {
146
0
            if (iequal(Derived::name, "embed") && config.endpoint.ends_with(":embedContent")) {
147
0
                static constexpr std::string_view legacy_suffix = ":embedContent";
148
0
                config.endpoint.replace(config.endpoint.size() - legacy_suffix.size(),
149
0
                                        legacy_suffix.size(), ":batchEmbedContents");
150
0
                return;
151
0
            }
152
153
0
            if (!config.endpoint.ends_with("v1") && !config.endpoint.ends_with("v1beta")) {
154
0
                return;
155
0
            }
156
157
0
            std::string model_name = config.model_name;
158
0
            if (!model_name.starts_with("models/")) {
159
0
                model_name = "models/" + model_name;
160
0
            }
161
162
0
            config.endpoint += "/";
163
0
            config.endpoint += model_name;
164
0
            config.endpoint +=
165
0
                    iequal(Derived::name, "embed") ? ":batchEmbedContents" : ":generateContent";
166
0
            return;
167
0
        }
168
169
        // The endpoint `v1/completions` does not support `system_prompt`.
170
        // To ensure a clear structure and stable AI results.
171
        // Convert from `v1/completions` to `v1/chat/completions`
172
2
        if (config.endpoint.ends_with("v1/completions")) {
173
0
            static constexpr std::string_view legacy_suffix = "v1/completions";
174
0
            config.endpoint.replace(config.endpoint.size() - legacy_suffix.size(),
175
0
                                    legacy_suffix.size(), "v1/chat/completions");
176
0
        }
177
2
    }
Unexecuted instantiation: _ZN5doris10AIFunctionINS_17FunctionAIExtractEE18normalize_endpointERNS_10AIResourceE
_ZN5doris10AIFunctionINS_18FunctionAIGenerateEE18normalize_endpointERNS_10AIResourceE
Line
Count
Source
140
3
    static void normalize_endpoint(AIResource& config) {
141
        // 1. If users configure only the version root like `.../v1` or `.../v1beta`, append
142
        //    `models/<model>:batchEmbedContents` for `embed`, and `models/<model>:generateContent`
143
        //    for other AI scalar functions.
144
        // 2. `:embedContent` -> `:batchEmbedContents`
145
3
        if (iequal(config.provider_type, "GEMINI")) {
146
0
            if (iequal(Derived::name, "embed") && config.endpoint.ends_with(":embedContent")) {
147
0
                static constexpr std::string_view legacy_suffix = ":embedContent";
148
0
                config.endpoint.replace(config.endpoint.size() - legacy_suffix.size(),
149
0
                                        legacy_suffix.size(), ":batchEmbedContents");
150
0
                return;
151
0
            }
152
153
0
            if (!config.endpoint.ends_with("v1") && !config.endpoint.ends_with("v1beta")) {
154
0
                return;
155
0
            }
156
157
0
            std::string model_name = config.model_name;
158
0
            if (!model_name.starts_with("models/")) {
159
0
                model_name = "models/" + model_name;
160
0
            }
161
162
0
            config.endpoint += "/";
163
0
            config.endpoint += model_name;
164
0
            config.endpoint +=
165
0
                    iequal(Derived::name, "embed") ? ":batchEmbedContents" : ":generateContent";
166
0
            return;
167
0
        }
168
169
        // The endpoint `v1/completions` does not support `system_prompt`.
170
        // To ensure a clear structure and stable AI results.
171
        // Convert from `v1/completions` to `v1/chat/completions`
172
3
        if (config.endpoint.ends_with("v1/completions")) {
173
0
            static constexpr std::string_view legacy_suffix = "v1/completions";
174
0
            config.endpoint.replace(config.endpoint.size() - legacy_suffix.size(),
175
0
                                    legacy_suffix.size(), "v1/chat/completions");
176
0
        }
177
3
    }
Unexecuted instantiation: _ZN5doris10AIFunctionINS_14FunctionAIMaskEE18normalize_endpointERNS_10AIResourceE
_ZN5doris10AIFunctionINS_20FunctionAISimilarityEE18normalize_endpointERNS_10AIResourceE
Line
Count
Source
140
22
    static void normalize_endpoint(AIResource& config) {
141
        // 1. If users configure only the version root like `.../v1` or `.../v1beta`, append
142
        //    `models/<model>:batchEmbedContents` for `embed`, and `models/<model>:generateContent`
143
        //    for other AI scalar functions.
144
        // 2. `:embedContent` -> `:batchEmbedContents`
145
22
        if (iequal(config.provider_type, "GEMINI")) {
146
0
            if (iequal(Derived::name, "embed") && config.endpoint.ends_with(":embedContent")) {
147
0
                static constexpr std::string_view legacy_suffix = ":embedContent";
148
0
                config.endpoint.replace(config.endpoint.size() - legacy_suffix.size(),
149
0
                                        legacy_suffix.size(), ":batchEmbedContents");
150
0
                return;
151
0
            }
152
153
0
            if (!config.endpoint.ends_with("v1") && !config.endpoint.ends_with("v1beta")) {
154
0
                return;
155
0
            }
156
157
0
            std::string model_name = config.model_name;
158
0
            if (!model_name.starts_with("models/")) {
159
0
                model_name = "models/" + model_name;
160
0
            }
161
162
0
            config.endpoint += "/";
163
0
            config.endpoint += model_name;
164
0
            config.endpoint +=
165
0
                    iequal(Derived::name, "embed") ? ":batchEmbedContents" : ":generateContent";
166
0
            return;
167
0
        }
168
169
        // The endpoint `v1/completions` does not support `system_prompt`.
170
        // To ensure a clear structure and stable AI results.
171
        // Convert from `v1/completions` to `v1/chat/completions`
172
22
        if (config.endpoint.ends_with("v1/completions")) {
173
0
            static constexpr std::string_view legacy_suffix = "v1/completions";
174
0
            config.endpoint.replace(config.endpoint.size() - legacy_suffix.size(),
175
0
                                    legacy_suffix.size(), "v1/chat/completions");
176
0
        }
177
22
    }
Unexecuted instantiation: _ZN5doris10AIFunctionINS_19FunctionAITranslateEE18normalize_endpointERNS_10AIResourceE
178
179
    Status send_request_to_llm(const std::string& request_body, std::string& response,
180
                               const AIResource& config, std::shared_ptr<AIAdapter>& adapter,
181
49
                               FunctionContext* context) const {
182
        // Retain the cache across batches/Blocks.
183
49
        auto* executor = static_cast<AIRequestExecutor*>(
184
49
                context->get_function_state(FunctionContext::THREAD_LOCAL));
185
49
        if (executor == nullptr) {
186
11
            auto state = std::make_shared<AIRequestExecutor>();
187
11
            executor = state.get();
188
11
            context->set_function_state(FunctionContext::THREAD_LOCAL, std::move(state));
189
11
        }
190
49
        return executor->execute(request_body, response, config, *adapter,
191
49
                                 context->state()->get_query_ctx());
192
49
    }
_ZNK5doris10AIFunctionINS_13FunctionEmbedEE19send_request_to_llmERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERS8_RKNS_10AIResourceERSt10shared_ptrINS_9AIAdapterEEPNS_15FunctionContextE
Line
Count
Source
181
31
                               FunctionContext* context) const {
182
        // Retain the cache across batches/Blocks.
183
31
        auto* executor = static_cast<AIRequestExecutor*>(
184
31
                context->get_function_state(FunctionContext::THREAD_LOCAL));
185
31
        if (executor == nullptr) {
186
6
            auto state = std::make_shared<AIRequestExecutor>();
187
6
            executor = state.get();
188
6
            context->set_function_state(FunctionContext::THREAD_LOCAL, std::move(state));
189
6
        }
190
31
        return executor->execute(request_body, response, config, *adapter,
191
31
                                 context->state()->get_query_ctx());
192
31
    }
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_16FunctionAIFilterEE19send_request_to_llmERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERS8_RKNS_10AIResourceERSt10shared_ptrINS_9AIAdapterEEPNS_15FunctionContextE
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_20FunctionAIFixGrammarEE19send_request_to_llmERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERS8_RKNS_10AIResourceERSt10shared_ptrINS_9AIAdapterEEPNS_15FunctionContextE
_ZNK5doris10AIFunctionINS_19FunctionAISentimentEE19send_request_to_llmERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERS8_RKNS_10AIResourceERSt10shared_ptrINS_9AIAdapterEEPNS_15FunctionContextE
Line
Count
Source
181
3
                               FunctionContext* context) const {
182
        // Retain the cache across batches/Blocks.
183
3
        auto* executor = static_cast<AIRequestExecutor*>(
184
3
                context->get_function_state(FunctionContext::THREAD_LOCAL));
185
3
        if (executor == nullptr) {
186
3
            auto state = std::make_shared<AIRequestExecutor>();
187
3
            executor = state.get();
188
3
            context->set_function_state(FunctionContext::THREAD_LOCAL, std::move(state));
189
3
        }
190
3
        return executor->execute(request_body, response, config, *adapter,
191
3
                                 context->state()->get_query_ctx());
192
3
    }
_ZNK5doris10AIFunctionINS_19FunctionAISummarizeEE19send_request_to_llmERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERS8_RKNS_10AIResourceERSt10shared_ptrINS_9AIAdapterEEPNS_15FunctionContextE
Line
Count
Source
181
15
                               FunctionContext* context) const {
182
        // Retain the cache across batches/Blocks.
183
15
        auto* executor = static_cast<AIRequestExecutor*>(
184
15
                context->get_function_state(FunctionContext::THREAD_LOCAL));
185
15
        if (executor == nullptr) {
186
2
            auto state = std::make_shared<AIRequestExecutor>();
187
2
            executor = state.get();
188
2
            context->set_function_state(FunctionContext::THREAD_LOCAL, std::move(state));
189
2
        }
190
15
        return executor->execute(request_body, response, config, *adapter,
191
15
                                 context->state()->get_query_ctx());
192
15
    }
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_18FunctionAIClassifyEE19send_request_to_llmERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERS8_RKNS_10AIResourceERSt10shared_ptrINS_9AIAdapterEEPNS_15FunctionContextE
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_17FunctionAIExtractEE19send_request_to_llmERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERS8_RKNS_10AIResourceERSt10shared_ptrINS_9AIAdapterEEPNS_15FunctionContextE
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_18FunctionAIGenerateEE19send_request_to_llmERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERS8_RKNS_10AIResourceERSt10shared_ptrINS_9AIAdapterEEPNS_15FunctionContextE
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_14FunctionAIMaskEE19send_request_to_llmERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERS8_RKNS_10AIResourceERSt10shared_ptrINS_9AIAdapterEEPNS_15FunctionContextE
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_20FunctionAISimilarityEE19send_request_to_llmERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERS8_RKNS_10AIResourceERSt10shared_ptrINS_9AIAdapterEEPNS_15FunctionContextE
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_19FunctionAITranslateEE19send_request_to_llmERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERS8_RKNS_10AIResourceERSt10shared_ptrINS_9AIAdapterEEPNS_15FunctionContextE
193
194
    // Provider-reusable helper for string-returning functions.
195
    // Estimates one batch entry size using the raw prompt length plus the fixed JSON wrapper cost.
196
110
    size_t estimate_batch_entry_size(size_t idx, const std::string& prompt) const {
197
110
        static constexpr size_t json_wrapper_size = 20;
198
110
        return prompt.size() + std::to_string(idx).size() + json_wrapper_size;
199
110
    }
_ZNK5doris10AIFunctionINS_16FunctionAIFilterEE25estimate_batch_entry_sizeEmRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
Line
Count
Source
196
64
    size_t estimate_batch_entry_size(size_t idx, const std::string& prompt) const {
197
64
        static constexpr size_t json_wrapper_size = 20;
198
64
        return prompt.size() + std::to_string(idx).size() + json_wrapper_size;
199
64
    }
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_20FunctionAIFixGrammarEE25estimate_batch_entry_sizeEmRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
_ZNK5doris10AIFunctionINS_19FunctionAISentimentEE25estimate_batch_entry_sizeEmRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
Line
Count
Source
196
4
    size_t estimate_batch_entry_size(size_t idx, const std::string& prompt) const {
197
4
        static constexpr size_t json_wrapper_size = 20;
198
4
        return prompt.size() + std::to_string(idx).size() + json_wrapper_size;
199
4
    }
_ZNK5doris10AIFunctionINS_19FunctionAISummarizeEE25estimate_batch_entry_sizeEmRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
Line
Count
Source
196
10
    size_t estimate_batch_entry_size(size_t idx, const std::string& prompt) const {
197
10
        static constexpr size_t json_wrapper_size = 20;
198
10
        return prompt.size() + std::to_string(idx).size() + json_wrapper_size;
199
10
    }
_ZNK5doris10AIFunctionINS_18FunctionAIClassifyEE25estimate_batch_entry_sizeEmRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
Line
Count
Source
196
2
    size_t estimate_batch_entry_size(size_t idx, const std::string& prompt) const {
197
2
        static constexpr size_t json_wrapper_size = 20;
198
2
        return prompt.size() + std::to_string(idx).size() + json_wrapper_size;
199
2
    }
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_17FunctionAIExtractEE25estimate_batch_entry_sizeEmRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
_ZNK5doris10AIFunctionINS_18FunctionAIGenerateEE25estimate_batch_entry_sizeEmRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
Line
Count
Source
196
5
    size_t estimate_batch_entry_size(size_t idx, const std::string& prompt) const {
197
5
        static constexpr size_t json_wrapper_size = 20;
198
5
        return prompt.size() + std::to_string(idx).size() + json_wrapper_size;
199
5
    }
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_14FunctionAIMaskEE25estimate_batch_entry_sizeEmRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
_ZNK5doris10AIFunctionINS_20FunctionAISimilarityEE25estimate_batch_entry_sizeEmRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
Line
Count
Source
196
25
    size_t estimate_batch_entry_size(size_t idx, const std::string& prompt) const {
197
25
        static constexpr size_t json_wrapper_size = 20;
198
25
        return prompt.size() + std::to_string(idx).size() + json_wrapper_size;
199
25
    }
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_19FunctionAITranslateEE25estimate_batch_entry_sizeEmRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
200
201
    // Provider-reusable helper for string-returning functions.
202
    // Executes one batch request and parses the provider result into one string per input row.
203
    Status execute_batch_request(const std::vector<std::string>& batch_prompts,
204
                                 std::vector<std::string>& results, const AIResource& config,
205
                                 std::shared_ptr<AIAdapter>& adapter,
206
0
                                 FunctionContext* context) const {
207
#ifdef BE_TEST
208
        const char* test_result = std::getenv("AI_TEST_RESULT");
209
        if (test_result != nullptr) {
210
            std::vector<std::string> parsed_test_response;
211
            RETURN_IF_ERROR(
212
                    adapter->parse_response(std::string(test_result), parsed_test_response));
213
            if (parsed_test_response.empty()) {
214
                return Status::InternalError("AI returned empty result");
215
            }
216
            if (parsed_test_response.size() != batch_prompts.size()) {
217
                return Status::RuntimeError(
218
                        "Failed to parse {} batch result, expected {} items but got {}", get_name(),
219
                        batch_prompts.size(), parsed_test_response.size());
220
            }
221
            results = std::move(parsed_test_response);
222
            return Status::OK();
223
        }
224
        if (config.provider_type == "MOCK") {
225
            results.clear();
226
            results.reserve(batch_prompts.size());
227
            for (const auto& prompt : batch_prompts) {
228
                results.emplace_back("this is a mock response. " + prompt);
229
            }
230
            return Status::OK();
231
        }
232
#endif
233
234
0
        std::string batch_prompt;
235
0
        RETURN_IF_ERROR(build_batch_prompt(batch_prompts, batch_prompt));
236
237
0
        std::vector<std::string> inputs = {batch_prompt};
238
0
        std::vector<std::string> parsed_response;
239
240
0
        std::string request_body;
241
0
        RETURN_IF_ERROR(adapter->build_request_payload(
242
0
                inputs, assert_cast<const Derived&>(*this).system_prompt, request_body));
243
244
0
        std::string response;
245
0
        RETURN_IF_ERROR(send_request_to_llm(request_body, response, config, adapter, context));
246
0
        RETURN_IF_ERROR(adapter->parse_response(response, parsed_response));
247
0
        if (parsed_response.empty()) {
248
0
            return Status::InternalError("AI returned empty result");
249
0
        }
250
0
        if (parsed_response.size() != batch_prompts.size()) {
251
0
            LOG(WARNING) << "AI batch result size mismatch, function=" << get_name()
252
0
                         << ", provider=" << config.provider_type << ", model=" << config.model_name
253
0
                         << ", expected_rows=" << batch_prompts.size()
254
0
                         << ", actual_rows=" << parsed_response.size()
255
0
                         << ", response_body=" << response;
256
0
            return Status::RuntimeError(
257
0
                    "Failed to parse {} batch result, expected {} items but got {}", get_name(),
258
0
                    batch_prompts.size(), parsed_response.size());
259
0
        }
260
0
        results = std::move(parsed_response);
261
0
        return Status::OK();
262
0
    }
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_16FunctionAIFilterEE21execute_batch_requestERKSt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS9_EERSB_RKNS_10AIResourceERSt10shared_ptrINS_9AIAdapterEEPNS_15FunctionContextE
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_20FunctionAIFixGrammarEE21execute_batch_requestERKSt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS9_EERSB_RKNS_10AIResourceERSt10shared_ptrINS_9AIAdapterEEPNS_15FunctionContextE
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_19FunctionAISentimentEE21execute_batch_requestERKSt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS9_EERSB_RKNS_10AIResourceERSt10shared_ptrINS_9AIAdapterEEPNS_15FunctionContextE
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_19FunctionAISummarizeEE21execute_batch_requestERKSt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS9_EERSB_RKNS_10AIResourceERSt10shared_ptrINS_9AIAdapterEEPNS_15FunctionContextE
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_18FunctionAIClassifyEE21execute_batch_requestERKSt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS9_EERSB_RKNS_10AIResourceERSt10shared_ptrINS_9AIAdapterEEPNS_15FunctionContextE
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_17FunctionAIExtractEE21execute_batch_requestERKSt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS9_EERSB_RKNS_10AIResourceERSt10shared_ptrINS_9AIAdapterEEPNS_15FunctionContextE
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_18FunctionAIGenerateEE21execute_batch_requestERKSt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS9_EERSB_RKNS_10AIResourceERSt10shared_ptrINS_9AIAdapterEEPNS_15FunctionContextE
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_14FunctionAIMaskEE21execute_batch_requestERKSt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS9_EERSB_RKNS_10AIResourceERSt10shared_ptrINS_9AIAdapterEEPNS_15FunctionContextE
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_20FunctionAISimilarityEE21execute_batch_requestERKSt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS9_EERSB_RKNS_10AIResourceERSt10shared_ptrINS_9AIAdapterEEPNS_15FunctionContextE
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_19FunctionAITranslateEE21execute_batch_requestERKSt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS9_EERSB_RKNS_10AIResourceERSt10shared_ptrINS_9AIAdapterEEPNS_15FunctionContextE
263
264
    // Provider-reusable helper for string-returning functions.
265
    // Runs the common batch execution flow; derived classes only need to define how one batch of
266
    // string results is inserted into the final output column.
267
    Status execute(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
268
                   uint32_t result, size_t input_rows_count, const AIResource& config,
269
81
                   std::shared_ptr<AIAdapter>& adapter) const {
270
81
        Columns prompt_columns;
271
81
        prompt_columns.reserve(arguments.size() - 1);
272
81
        ColumnUInt8::MutablePtr result_null_map;
273
186
        for (size_t i = 1; i < arguments.size(); ++i) {
274
105
            const auto& argument = block.get_by_position(arguments[i]);
275
105
            if (argument.type->is_nullable()) {
276
12
                const auto& [column, is_const] = unpack_if_const(argument.column);
277
12
                const auto& nullable =
278
12
                        assert_cast<const ColumnNullable&, TypeCheckOnRelease::DISABLE>(*column);
279
12
                if (!result_null_map) {
280
11
                    result_null_map = ColumnUInt8::create(input_rows_count, 0);
281
11
                }
282
12
                VectorizedUtils::update_null_map(result_null_map->get_data(),
283
12
                                                 nullable.get_null_map_data(), is_const);
284
12
            }
285
105
            prompt_columns.emplace_back(
286
105
                    argument.unnest_nullable(argument.type->is_nullable()
287
105
                                                     ? argument.get_nullable_column_info()
288
105
                                                     : NullableColumnInfo {},
289
105
                                             false)
290
105
                            .column);
291
105
        }
292
293
81
        if (result_null_map &&
294
81
            !simd::contain_zero(result_null_map->get_data().data(), input_rows_count)) {
295
1
            block.get_by_position(result).column =
296
1
                    block.get_by_position(result).type->create_column_const(input_rows_count,
297
1
                                                                            Field());
298
1
            return Status::OK();
299
1
        }
300
301
80
        auto col_result = assert_cast<const Derived&>(*this).create_result_column();
302
80
        std::vector<std::string> batch_prompts;
303
80
        size_t current_batch_size = 2; // []
304
80
        const size_t max_batch_prompt_size =
305
80
                static_cast<size_t>(get_ai_context_window_size(context));
306
80
        const NullMap* null_map = result_null_map ? &result_null_map->get_data() : nullptr;
307
308
204
        for (size_t i = 0; i < input_rows_count; ++i) {
309
124
            if (null_map && (*null_map)[i]) {
310
14
                continue;
311
14
            }
312
313
110
            std::string prompt;
314
110
            RETURN_IF_ERROR(
315
110
                    assert_cast<const Derived&>(*this).build_prompt(prompt_columns, i, prompt));
316
317
110
            size_t entry_size = estimate_batch_entry_size(batch_prompts.size(), prompt);
318
110
            if (entry_size > max_batch_prompt_size) {
319
14
                if (!batch_prompts.empty()) {
320
1
                    std::vector<std::string> batch_results;
321
1
                    RETURN_IF_ERROR(this->execute_batch_request(batch_prompts, batch_results,
322
1
                                                                config, adapter, context));
323
1
                    RETURN_IF_ERROR(assert_cast<const Derived&>(*this).append_batch_results(
324
1
                            batch_results, *col_result));
325
1
                    batch_prompts.clear();
326
1
                    current_batch_size = 2;
327
1
                }
328
329
14
                std::vector<std::string> single_prompts;
330
14
                single_prompts.emplace_back(std::move(prompt));
331
14
                std::vector<std::string> single_results;
332
14
                RETURN_IF_ERROR(this->execute_batch_request(single_prompts, single_results, config,
333
14
                                                            adapter, context));
334
14
                RETURN_IF_ERROR(assert_cast<const Derived&>(*this).append_batch_results(
335
14
                        single_results, *col_result));
336
14
                continue;
337
14
            }
338
339
96
            size_t additional_size = entry_size + (batch_prompts.empty() ? 0 : 1);
340
96
            if (!batch_prompts.empty() &&
341
96
                current_batch_size + additional_size > max_batch_prompt_size) {
342
2
                std::vector<std::string> batch_results;
343
2
                RETURN_IF_ERROR(this->execute_batch_request(batch_prompts, batch_results, config,
344
2
                                                            adapter, context));
345
2
                RETURN_IF_ERROR(assert_cast<const Derived&>(*this).append_batch_results(
346
2
                        batch_results, *col_result));
347
2
                batch_prompts.clear();
348
2
                current_batch_size = 2;
349
2
                additional_size = entry_size;
350
2
            }
351
352
96
            batch_prompts.emplace_back(std::move(prompt));
353
96
            current_batch_size += additional_size;
354
96
        }
355
356
80
        if (!batch_prompts.empty()) {
357
72
            std::vector<std::string> batch_results;
358
72
            RETURN_IF_ERROR(this->execute_batch_request(batch_prompts, batch_results, config,
359
72
                                                        adapter, context));
360
66
            RETURN_IF_ERROR(assert_cast<const Derived&>(*this).append_batch_results(batch_results,
361
66
                                                                                    *col_result));
362
66
        }
363
364
47
        if (!result_null_map) {
365
37
            block.replace_by_position(result, std::move(col_result));
366
37
            return Status::OK();
367
37
        }
368
369
10
        if (!simd::contain_one(result_null_map->get_data().data(), input_rows_count)) {
370
1
            block.replace_by_position(result, ColumnNullable::create(std::move(col_result),
371
1
                                                                     std::move(result_null_map)));
372
1
            return Status::OK();
373
1
        }
374
375
9
        auto nested_result = col_result->clone_empty();
376
9
        size_t result_row = 0;
377
31
        for (UInt8 is_null : result_null_map->get_data()) {
378
31
            if (is_null) {
379
14
                nested_result->insert_default();
380
17
            } else {
381
17
                nested_result->insert_from(*col_result, result_row++);
382
17
            }
383
31
        }
384
385
9
        block.replace_by_position(result, ColumnNullable::create(std::move(nested_result),
386
9
                                                                 std::move(result_null_map)));
387
9
        return Status::OK();
388
10
    }
_ZNK5doris10AIFunctionINS_16FunctionAIFilterEE7executeEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjmRKNS_10AIResourceERSt10shared_ptrINS_9AIAdapterEE
Line
Count
Source
269
47
                   std::shared_ptr<AIAdapter>& adapter) const {
270
47
        Columns prompt_columns;
271
47
        prompt_columns.reserve(arguments.size() - 1);
272
47
        ColumnUInt8::MutablePtr result_null_map;
273
94
        for (size_t i = 1; i < arguments.size(); ++i) {
274
47
            const auto& argument = block.get_by_position(arguments[i]);
275
47
            if (argument.type->is_nullable()) {
276
1
                const auto& [column, is_const] = unpack_if_const(argument.column);
277
1
                const auto& nullable =
278
1
                        assert_cast<const ColumnNullable&, TypeCheckOnRelease::DISABLE>(*column);
279
1
                if (!result_null_map) {
280
1
                    result_null_map = ColumnUInt8::create(input_rows_count, 0);
281
1
                }
282
1
                VectorizedUtils::update_null_map(result_null_map->get_data(),
283
1
                                                 nullable.get_null_map_data(), is_const);
284
1
            }
285
47
            prompt_columns.emplace_back(
286
47
                    argument.unnest_nullable(argument.type->is_nullable()
287
47
                                                     ? argument.get_nullable_column_info()
288
47
                                                     : NullableColumnInfo {},
289
47
                                             false)
290
47
                            .column);
291
47
        }
292
293
47
        if (result_null_map &&
294
47
            !simd::contain_zero(result_null_map->get_data().data(), input_rows_count)) {
295
0
            block.get_by_position(result).column =
296
0
                    block.get_by_position(result).type->create_column_const(input_rows_count,
297
0
                                                                            Field());
298
0
            return Status::OK();
299
0
        }
300
301
47
        auto col_result = assert_cast<const Derived&>(*this).create_result_column();
302
47
        std::vector<std::string> batch_prompts;
303
47
        size_t current_batch_size = 2; // []
304
47
        const size_t max_batch_prompt_size =
305
47
                static_cast<size_t>(get_ai_context_window_size(context));
306
47
        const NullMap* null_map = result_null_map ? &result_null_map->get_data() : nullptr;
307
308
113
        for (size_t i = 0; i < input_rows_count; ++i) {
309
66
            if (null_map && (*null_map)[i]) {
310
2
                continue;
311
2
            }
312
313
64
            std::string prompt;
314
64
            RETURN_IF_ERROR(
315
64
                    assert_cast<const Derived&>(*this).build_prompt(prompt_columns, i, prompt));
316
317
64
            size_t entry_size = estimate_batch_entry_size(batch_prompts.size(), prompt);
318
64
            if (entry_size > max_batch_prompt_size) {
319
4
                if (!batch_prompts.empty()) {
320
1
                    std::vector<std::string> batch_results;
321
1
                    RETURN_IF_ERROR(this->execute_batch_request(batch_prompts, batch_results,
322
1
                                                                config, adapter, context));
323
1
                    RETURN_IF_ERROR(assert_cast<const Derived&>(*this).append_batch_results(
324
1
                            batch_results, *col_result));
325
1
                    batch_prompts.clear();
326
1
                    current_batch_size = 2;
327
1
                }
328
329
4
                std::vector<std::string> single_prompts;
330
4
                single_prompts.emplace_back(std::move(prompt));
331
4
                std::vector<std::string> single_results;
332
4
                RETURN_IF_ERROR(this->execute_batch_request(single_prompts, single_results, config,
333
4
                                                            adapter, context));
334
4
                RETURN_IF_ERROR(assert_cast<const Derived&>(*this).append_batch_results(
335
4
                        single_results, *col_result));
336
4
                continue;
337
4
            }
338
339
60
            size_t additional_size = entry_size + (batch_prompts.empty() ? 0 : 1);
340
60
            if (!batch_prompts.empty() &&
341
60
                current_batch_size + additional_size > max_batch_prompt_size) {
342
2
                std::vector<std::string> batch_results;
343
2
                RETURN_IF_ERROR(this->execute_batch_request(batch_prompts, batch_results, config,
344
2
                                                            adapter, context));
345
2
                RETURN_IF_ERROR(assert_cast<const Derived&>(*this).append_batch_results(
346
2
                        batch_results, *col_result));
347
2
                batch_prompts.clear();
348
2
                current_batch_size = 2;
349
2
                additional_size = entry_size;
350
2
            }
351
352
60
            batch_prompts.emplace_back(std::move(prompt));
353
60
            current_batch_size += additional_size;
354
60
        }
355
356
47
        if (!batch_prompts.empty()) {
357
44
            std::vector<std::string> batch_results;
358
44
            RETURN_IF_ERROR(this->execute_batch_request(batch_prompts, batch_results, config,
359
44
                                                        adapter, context));
360
38
            RETURN_IF_ERROR(assert_cast<const Derived&>(*this).append_batch_results(batch_results,
361
38
                                                                                    *col_result));
362
38
        }
363
364
20
        if (!result_null_map) {
365
19
            block.replace_by_position(result, std::move(col_result));
366
19
            return Status::OK();
367
19
        }
368
369
1
        if (!simd::contain_one(result_null_map->get_data().data(), input_rows_count)) {
370
0
            block.replace_by_position(result, ColumnNullable::create(std::move(col_result),
371
0
                                                                     std::move(result_null_map)));
372
0
            return Status::OK();
373
0
        }
374
375
1
        auto nested_result = col_result->clone_empty();
376
1
        size_t result_row = 0;
377
4
        for (UInt8 is_null : result_null_map->get_data()) {
378
4
            if (is_null) {
379
2
                nested_result->insert_default();
380
2
            } else {
381
2
                nested_result->insert_from(*col_result, result_row++);
382
2
            }
383
4
        }
384
385
1
        block.replace_by_position(result, ColumnNullable::create(std::move(nested_result),
386
1
                                                                 std::move(result_null_map)));
387
1
        return Status::OK();
388
1
    }
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_20FunctionAIFixGrammarEE7executeEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjmRKNS_10AIResourceERSt10shared_ptrINS_9AIAdapterEE
_ZNK5doris10AIFunctionINS_19FunctionAISentimentEE7executeEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjmRKNS_10AIResourceERSt10shared_ptrINS_9AIAdapterEE
Line
Count
Source
269
2
                   std::shared_ptr<AIAdapter>& adapter) const {
270
2
        Columns prompt_columns;
271
2
        prompt_columns.reserve(arguments.size() - 1);
272
2
        ColumnUInt8::MutablePtr result_null_map;
273
4
        for (size_t i = 1; i < arguments.size(); ++i) {
274
2
            const auto& argument = block.get_by_position(arguments[i]);
275
2
            if (argument.type->is_nullable()) {
276
0
                const auto& [column, is_const] = unpack_if_const(argument.column);
277
0
                const auto& nullable =
278
0
                        assert_cast<const ColumnNullable&, TypeCheckOnRelease::DISABLE>(*column);
279
0
                if (!result_null_map) {
280
0
                    result_null_map = ColumnUInt8::create(input_rows_count, 0);
281
0
                }
282
0
                VectorizedUtils::update_null_map(result_null_map->get_data(),
283
0
                                                 nullable.get_null_map_data(), is_const);
284
0
            }
285
2
            prompt_columns.emplace_back(
286
2
                    argument.unnest_nullable(argument.type->is_nullable()
287
2
                                                     ? argument.get_nullable_column_info()
288
2
                                                     : NullableColumnInfo {},
289
2
                                             false)
290
2
                            .column);
291
2
        }
292
293
2
        if (result_null_map &&
294
2
            !simd::contain_zero(result_null_map->get_data().data(), input_rows_count)) {
295
0
            block.get_by_position(result).column =
296
0
                    block.get_by_position(result).type->create_column_const(input_rows_count,
297
0
                                                                            Field());
298
0
            return Status::OK();
299
0
        }
300
301
2
        auto col_result = assert_cast<const Derived&>(*this).create_result_column();
302
2
        std::vector<std::string> batch_prompts;
303
2
        size_t current_batch_size = 2; // []
304
2
        const size_t max_batch_prompt_size =
305
2
                static_cast<size_t>(get_ai_context_window_size(context));
306
2
        const NullMap* null_map = result_null_map ? &result_null_map->get_data() : nullptr;
307
308
6
        for (size_t i = 0; i < input_rows_count; ++i) {
309
4
            if (null_map && (*null_map)[i]) {
310
0
                continue;
311
0
            }
312
313
4
            std::string prompt;
314
4
            RETURN_IF_ERROR(
315
4
                    assert_cast<const Derived&>(*this).build_prompt(prompt_columns, i, prompt));
316
317
4
            size_t entry_size = estimate_batch_entry_size(batch_prompts.size(), prompt);
318
4
            if (entry_size > max_batch_prompt_size) {
319
0
                if (!batch_prompts.empty()) {
320
0
                    std::vector<std::string> batch_results;
321
0
                    RETURN_IF_ERROR(this->execute_batch_request(batch_prompts, batch_results,
322
0
                                                                config, adapter, context));
323
0
                    RETURN_IF_ERROR(assert_cast<const Derived&>(*this).append_batch_results(
324
0
                            batch_results, *col_result));
325
0
                    batch_prompts.clear();
326
0
                    current_batch_size = 2;
327
0
                }
328
329
0
                std::vector<std::string> single_prompts;
330
0
                single_prompts.emplace_back(std::move(prompt));
331
0
                std::vector<std::string> single_results;
332
0
                RETURN_IF_ERROR(this->execute_batch_request(single_prompts, single_results, config,
333
0
                                                            adapter, context));
334
0
                RETURN_IF_ERROR(assert_cast<const Derived&>(*this).append_batch_results(
335
0
                        single_results, *col_result));
336
0
                continue;
337
0
            }
338
339
4
            size_t additional_size = entry_size + (batch_prompts.empty() ? 0 : 1);
340
4
            if (!batch_prompts.empty() &&
341
4
                current_batch_size + additional_size > max_batch_prompt_size) {
342
0
                std::vector<std::string> batch_results;
343
0
                RETURN_IF_ERROR(this->execute_batch_request(batch_prompts, batch_results, config,
344
0
                                                            adapter, context));
345
0
                RETURN_IF_ERROR(assert_cast<const Derived&>(*this).append_batch_results(
346
0
                        batch_results, *col_result));
347
0
                batch_prompts.clear();
348
0
                current_batch_size = 2;
349
0
                additional_size = entry_size;
350
0
            }
351
352
4
            batch_prompts.emplace_back(std::move(prompt));
353
4
            current_batch_size += additional_size;
354
4
        }
355
356
2
        if (!batch_prompts.empty()) {
357
2
            std::vector<std::string> batch_results;
358
2
            RETURN_IF_ERROR(this->execute_batch_request(batch_prompts, batch_results, config,
359
2
                                                        adapter, context));
360
2
            RETURN_IF_ERROR(assert_cast<const Derived&>(*this).append_batch_results(batch_results,
361
2
                                                                                    *col_result));
362
2
        }
363
364
2
        if (!result_null_map) {
365
2
            block.replace_by_position(result, std::move(col_result));
366
2
            return Status::OK();
367
2
        }
368
369
0
        if (!simd::contain_one(result_null_map->get_data().data(), input_rows_count)) {
370
0
            block.replace_by_position(result, ColumnNullable::create(std::move(col_result),
371
0
                                                                     std::move(result_null_map)));
372
0
            return Status::OK();
373
0
        }
374
375
0
        auto nested_result = col_result->clone_empty();
376
0
        size_t result_row = 0;
377
0
        for (UInt8 is_null : result_null_map->get_data()) {
378
0
            if (is_null) {
379
0
                nested_result->insert_default();
380
0
            } else {
381
0
                nested_result->insert_from(*col_result, result_row++);
382
0
            }
383
0
        }
384
385
0
        block.replace_by_position(result, ColumnNullable::create(std::move(nested_result),
386
0
                                                                 std::move(result_null_map)));
387
0
        return Status::OK();
388
0
    }
_ZNK5doris10AIFunctionINS_19FunctionAISummarizeEE7executeEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjmRKNS_10AIResourceERSt10shared_ptrINS_9AIAdapterEE
Line
Count
Source
269
5
                   std::shared_ptr<AIAdapter>& adapter) const {
270
5
        Columns prompt_columns;
271
5
        prompt_columns.reserve(arguments.size() - 1);
272
5
        ColumnUInt8::MutablePtr result_null_map;
273
10
        for (size_t i = 1; i < arguments.size(); ++i) {
274
5
            const auto& argument = block.get_by_position(arguments[i]);
275
5
            if (argument.type->is_nullable()) {
276
5
                const auto& [column, is_const] = unpack_if_const(argument.column);
277
5
                const auto& nullable =
278
5
                        assert_cast<const ColumnNullable&, TypeCheckOnRelease::DISABLE>(*column);
279
5
                if (!result_null_map) {
280
5
                    result_null_map = ColumnUInt8::create(input_rows_count, 0);
281
5
                }
282
5
                VectorizedUtils::update_null_map(result_null_map->get_data(),
283
5
                                                 nullable.get_null_map_data(), is_const);
284
5
            }
285
5
            prompt_columns.emplace_back(
286
5
                    argument.unnest_nullable(argument.type->is_nullable()
287
5
                                                     ? argument.get_nullable_column_info()
288
5
                                                     : NullableColumnInfo {},
289
5
                                             false)
290
5
                            .column);
291
5
        }
292
293
5
        if (result_null_map &&
294
5
            !simd::contain_zero(result_null_map->get_data().data(), input_rows_count)) {
295
0
            block.get_by_position(result).column =
296
0
                    block.get_by_position(result).type->create_column_const(input_rows_count,
297
0
                                                                            Field());
298
0
            return Status::OK();
299
0
        }
300
301
5
        auto col_result = assert_cast<const Derived&>(*this).create_result_column();
302
5
        std::vector<std::string> batch_prompts;
303
5
        size_t current_batch_size = 2; // []
304
5
        const size_t max_batch_prompt_size =
305
5
                static_cast<size_t>(get_ai_context_window_size(context));
306
5
        const NullMap* null_map = result_null_map ? &result_null_map->get_data() : nullptr;
307
308
20
        for (size_t i = 0; i < input_rows_count; ++i) {
309
15
            if (null_map && (*null_map)[i]) {
310
5
                continue;
311
5
            }
312
313
10
            std::string prompt;
314
10
            RETURN_IF_ERROR(
315
10
                    assert_cast<const Derived&>(*this).build_prompt(prompt_columns, i, prompt));
316
317
10
            size_t entry_size = estimate_batch_entry_size(batch_prompts.size(), prompt);
318
10
            if (entry_size > max_batch_prompt_size) {
319
10
                if (!batch_prompts.empty()) {
320
0
                    std::vector<std::string> batch_results;
321
0
                    RETURN_IF_ERROR(this->execute_batch_request(batch_prompts, batch_results,
322
0
                                                                config, adapter, context));
323
0
                    RETURN_IF_ERROR(assert_cast<const Derived&>(*this).append_batch_results(
324
0
                            batch_results, *col_result));
325
0
                    batch_prompts.clear();
326
0
                    current_batch_size = 2;
327
0
                }
328
329
10
                std::vector<std::string> single_prompts;
330
10
                single_prompts.emplace_back(std::move(prompt));
331
10
                std::vector<std::string> single_results;
332
10
                RETURN_IF_ERROR(this->execute_batch_request(single_prompts, single_results, config,
333
10
                                                            adapter, context));
334
10
                RETURN_IF_ERROR(assert_cast<const Derived&>(*this).append_batch_results(
335
10
                        single_results, *col_result));
336
10
                continue;
337
10
            }
338
339
0
            size_t additional_size = entry_size + (batch_prompts.empty() ? 0 : 1);
340
0
            if (!batch_prompts.empty() &&
341
0
                current_batch_size + additional_size > max_batch_prompt_size) {
342
0
                std::vector<std::string> batch_results;
343
0
                RETURN_IF_ERROR(this->execute_batch_request(batch_prompts, batch_results, config,
344
0
                                                            adapter, context));
345
0
                RETURN_IF_ERROR(assert_cast<const Derived&>(*this).append_batch_results(
346
0
                        batch_results, *col_result));
347
0
                batch_prompts.clear();
348
0
                current_batch_size = 2;
349
0
                additional_size = entry_size;
350
0
            }
351
352
0
            batch_prompts.emplace_back(std::move(prompt));
353
0
            current_batch_size += additional_size;
354
0
        }
355
356
5
        if (!batch_prompts.empty()) {
357
0
            std::vector<std::string> batch_results;
358
0
            RETURN_IF_ERROR(this->execute_batch_request(batch_prompts, batch_results, config,
359
0
                                                        adapter, context));
360
0
            RETURN_IF_ERROR(assert_cast<const Derived&>(*this).append_batch_results(batch_results,
361
0
                                                                                    *col_result));
362
0
        }
363
364
5
        if (!result_null_map) {
365
0
            block.replace_by_position(result, std::move(col_result));
366
0
            return Status::OK();
367
0
        }
368
369
5
        if (!simd::contain_one(result_null_map->get_data().data(), input_rows_count)) {
370
0
            block.replace_by_position(result, ColumnNullable::create(std::move(col_result),
371
0
                                                                     std::move(result_null_map)));
372
0
            return Status::OK();
373
0
        }
374
375
5
        auto nested_result = col_result->clone_empty();
376
5
        size_t result_row = 0;
377
15
        for (UInt8 is_null : result_null_map->get_data()) {
378
15
            if (is_null) {
379
5
                nested_result->insert_default();
380
10
            } else {
381
10
                nested_result->insert_from(*col_result, result_row++);
382
10
            }
383
15
        }
384
385
5
        block.replace_by_position(result, ColumnNullable::create(std::move(nested_result),
386
5
                                                                 std::move(result_null_map)));
387
5
        return Status::OK();
388
5
    }
_ZNK5doris10AIFunctionINS_18FunctionAIClassifyEE7executeEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjmRKNS_10AIResourceERSt10shared_ptrINS_9AIAdapterEE
Line
Count
Source
269
2
                   std::shared_ptr<AIAdapter>& adapter) const {
270
2
        Columns prompt_columns;
271
2
        prompt_columns.reserve(arguments.size() - 1);
272
2
        ColumnUInt8::MutablePtr result_null_map;
273
6
        for (size_t i = 1; i < arguments.size(); ++i) {
274
4
            const auto& argument = block.get_by_position(arguments[i]);
275
4
            if (argument.type->is_nullable()) {
276
1
                const auto& [column, is_const] = unpack_if_const(argument.column);
277
1
                const auto& nullable =
278
1
                        assert_cast<const ColumnNullable&, TypeCheckOnRelease::DISABLE>(*column);
279
1
                if (!result_null_map) {
280
1
                    result_null_map = ColumnUInt8::create(input_rows_count, 0);
281
1
                }
282
1
                VectorizedUtils::update_null_map(result_null_map->get_data(),
283
1
                                                 nullable.get_null_map_data(), is_const);
284
1
            }
285
4
            prompt_columns.emplace_back(
286
4
                    argument.unnest_nullable(argument.type->is_nullable()
287
4
                                                     ? argument.get_nullable_column_info()
288
4
                                                     : NullableColumnInfo {},
289
4
                                             false)
290
4
                            .column);
291
4
        }
292
293
2
        if (result_null_map &&
294
2
            !simd::contain_zero(result_null_map->get_data().data(), input_rows_count)) {
295
0
            block.get_by_position(result).column =
296
0
                    block.get_by_position(result).type->create_column_const(input_rows_count,
297
0
                                                                            Field());
298
0
            return Status::OK();
299
0
        }
300
301
2
        auto col_result = assert_cast<const Derived&>(*this).create_result_column();
302
2
        std::vector<std::string> batch_prompts;
303
2
        size_t current_batch_size = 2; // []
304
2
        const size_t max_batch_prompt_size =
305
2
                static_cast<size_t>(get_ai_context_window_size(context));
306
2
        const NullMap* null_map = result_null_map ? &result_null_map->get_data() : nullptr;
307
308
6
        for (size_t i = 0; i < input_rows_count; ++i) {
309
4
            if (null_map && (*null_map)[i]) {
310
2
                continue;
311
2
            }
312
313
2
            std::string prompt;
314
2
            RETURN_IF_ERROR(
315
2
                    assert_cast<const Derived&>(*this).build_prompt(prompt_columns, i, prompt));
316
317
2
            size_t entry_size = estimate_batch_entry_size(batch_prompts.size(), prompt);
318
2
            if (entry_size > max_batch_prompt_size) {
319
0
                if (!batch_prompts.empty()) {
320
0
                    std::vector<std::string> batch_results;
321
0
                    RETURN_IF_ERROR(this->execute_batch_request(batch_prompts, batch_results,
322
0
                                                                config, adapter, context));
323
0
                    RETURN_IF_ERROR(assert_cast<const Derived&>(*this).append_batch_results(
324
0
                            batch_results, *col_result));
325
0
                    batch_prompts.clear();
326
0
                    current_batch_size = 2;
327
0
                }
328
329
0
                std::vector<std::string> single_prompts;
330
0
                single_prompts.emplace_back(std::move(prompt));
331
0
                std::vector<std::string> single_results;
332
0
                RETURN_IF_ERROR(this->execute_batch_request(single_prompts, single_results, config,
333
0
                                                            adapter, context));
334
0
                RETURN_IF_ERROR(assert_cast<const Derived&>(*this).append_batch_results(
335
0
                        single_results, *col_result));
336
0
                continue;
337
0
            }
338
339
2
            size_t additional_size = entry_size + (batch_prompts.empty() ? 0 : 1);
340
2
            if (!batch_prompts.empty() &&
341
2
                current_batch_size + additional_size > max_batch_prompt_size) {
342
0
                std::vector<std::string> batch_results;
343
0
                RETURN_IF_ERROR(this->execute_batch_request(batch_prompts, batch_results, config,
344
0
                                                            adapter, context));
345
0
                RETURN_IF_ERROR(assert_cast<const Derived&>(*this).append_batch_results(
346
0
                        batch_results, *col_result));
347
0
                batch_prompts.clear();
348
0
                current_batch_size = 2;
349
0
                additional_size = entry_size;
350
0
            }
351
352
2
            batch_prompts.emplace_back(std::move(prompt));
353
2
            current_batch_size += additional_size;
354
2
        }
355
356
2
        if (!batch_prompts.empty()) {
357
2
            std::vector<std::string> batch_results;
358
2
            RETURN_IF_ERROR(this->execute_batch_request(batch_prompts, batch_results, config,
359
2
                                                        adapter, context));
360
2
            RETURN_IF_ERROR(assert_cast<const Derived&>(*this).append_batch_results(batch_results,
361
2
                                                                                    *col_result));
362
2
        }
363
364
2
        if (!result_null_map) {
365
1
            block.replace_by_position(result, std::move(col_result));
366
1
            return Status::OK();
367
1
        }
368
369
1
        if (!simd::contain_one(result_null_map->get_data().data(), input_rows_count)) {
370
0
            block.replace_by_position(result, ColumnNullable::create(std::move(col_result),
371
0
                                                                     std::move(result_null_map)));
372
0
            return Status::OK();
373
0
        }
374
375
1
        auto nested_result = col_result->clone_empty();
376
1
        size_t result_row = 0;
377
3
        for (UInt8 is_null : result_null_map->get_data()) {
378
3
            if (is_null) {
379
2
                nested_result->insert_default();
380
2
            } else {
381
1
                nested_result->insert_from(*col_result, result_row++);
382
1
            }
383
3
        }
384
385
1
        block.replace_by_position(result, ColumnNullable::create(std::move(nested_result),
386
1
                                                                 std::move(result_null_map)));
387
1
        return Status::OK();
388
1
    }
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_17FunctionAIExtractEE7executeEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjmRKNS_10AIResourceERSt10shared_ptrINS_9AIAdapterEE
_ZNK5doris10AIFunctionINS_18FunctionAIGenerateEE7executeEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjmRKNS_10AIResourceERSt10shared_ptrINS_9AIAdapterEE
Line
Count
Source
269
3
                   std::shared_ptr<AIAdapter>& adapter) const {
270
3
        Columns prompt_columns;
271
3
        prompt_columns.reserve(arguments.size() - 1);
272
3
        ColumnUInt8::MutablePtr result_null_map;
273
6
        for (size_t i = 1; i < arguments.size(); ++i) {
274
3
            const auto& argument = block.get_by_position(arguments[i]);
275
3
            if (argument.type->is_nullable()) {
276
3
                const auto& [column, is_const] = unpack_if_const(argument.column);
277
3
                const auto& nullable =
278
3
                        assert_cast<const ColumnNullable&, TypeCheckOnRelease::DISABLE>(*column);
279
3
                if (!result_null_map) {
280
3
                    result_null_map = ColumnUInt8::create(input_rows_count, 0);
281
3
                }
282
3
                VectorizedUtils::update_null_map(result_null_map->get_data(),
283
3
                                                 nullable.get_null_map_data(), is_const);
284
3
            }
285
3
            prompt_columns.emplace_back(
286
3
                    argument.unnest_nullable(argument.type->is_nullable()
287
3
                                                     ? argument.get_nullable_column_info()
288
3
                                                     : NullableColumnInfo {},
289
3
                                             false)
290
3
                            .column);
291
3
        }
292
293
3
        if (result_null_map &&
294
3
            !simd::contain_zero(result_null_map->get_data().data(), input_rows_count)) {
295
1
            block.get_by_position(result).column =
296
1
                    block.get_by_position(result).type->create_column_const(input_rows_count,
297
1
                                                                            Field());
298
1
            return Status::OK();
299
1
        }
300
301
2
        auto col_result = assert_cast<const Derived&>(*this).create_result_column();
302
2
        std::vector<std::string> batch_prompts;
303
2
        size_t current_batch_size = 2; // []
304
2
        const size_t max_batch_prompt_size =
305
2
                static_cast<size_t>(get_ai_context_window_size(context));
306
2
        const NullMap* null_map = result_null_map ? &result_null_map->get_data() : nullptr;
307
308
10
        for (size_t i = 0; i < input_rows_count; ++i) {
309
8
            if (null_map && (*null_map)[i]) {
310
3
                continue;
311
3
            }
312
313
5
            std::string prompt;
314
5
            RETURN_IF_ERROR(
315
5
                    assert_cast<const Derived&>(*this).build_prompt(prompt_columns, i, prompt));
316
317
5
            size_t entry_size = estimate_batch_entry_size(batch_prompts.size(), prompt);
318
5
            if (entry_size > max_batch_prompt_size) {
319
0
                if (!batch_prompts.empty()) {
320
0
                    std::vector<std::string> batch_results;
321
0
                    RETURN_IF_ERROR(this->execute_batch_request(batch_prompts, batch_results,
322
0
                                                                config, adapter, context));
323
0
                    RETURN_IF_ERROR(assert_cast<const Derived&>(*this).append_batch_results(
324
0
                            batch_results, *col_result));
325
0
                    batch_prompts.clear();
326
0
                    current_batch_size = 2;
327
0
                }
328
329
0
                std::vector<std::string> single_prompts;
330
0
                single_prompts.emplace_back(std::move(prompt));
331
0
                std::vector<std::string> single_results;
332
0
                RETURN_IF_ERROR(this->execute_batch_request(single_prompts, single_results, config,
333
0
                                                            adapter, context));
334
0
                RETURN_IF_ERROR(assert_cast<const Derived&>(*this).append_batch_results(
335
0
                        single_results, *col_result));
336
0
                continue;
337
0
            }
338
339
5
            size_t additional_size = entry_size + (batch_prompts.empty() ? 0 : 1);
340
5
            if (!batch_prompts.empty() &&
341
5
                current_batch_size + additional_size > max_batch_prompt_size) {
342
0
                std::vector<std::string> batch_results;
343
0
                RETURN_IF_ERROR(this->execute_batch_request(batch_prompts, batch_results, config,
344
0
                                                            adapter, context));
345
0
                RETURN_IF_ERROR(assert_cast<const Derived&>(*this).append_batch_results(
346
0
                        batch_results, *col_result));
347
0
                batch_prompts.clear();
348
0
                current_batch_size = 2;
349
0
                additional_size = entry_size;
350
0
            }
351
352
5
            batch_prompts.emplace_back(std::move(prompt));
353
5
            current_batch_size += additional_size;
354
5
        }
355
356
2
        if (!batch_prompts.empty()) {
357
2
            std::vector<std::string> batch_results;
358
2
            RETURN_IF_ERROR(this->execute_batch_request(batch_prompts, batch_results, config,
359
2
                                                        adapter, context));
360
2
            RETURN_IF_ERROR(assert_cast<const Derived&>(*this).append_batch_results(batch_results,
361
2
                                                                                    *col_result));
362
2
        }
363
364
2
        if (!result_null_map) {
365
0
            block.replace_by_position(result, std::move(col_result));
366
0
            return Status::OK();
367
0
        }
368
369
2
        if (!simd::contain_one(result_null_map->get_data().data(), input_rows_count)) {
370
1
            block.replace_by_position(result, ColumnNullable::create(std::move(col_result),
371
1
                                                                     std::move(result_null_map)));
372
1
            return Status::OK();
373
1
        }
374
375
1
        auto nested_result = col_result->clone_empty();
376
1
        size_t result_row = 0;
377
5
        for (UInt8 is_null : result_null_map->get_data()) {
378
5
            if (is_null) {
379
3
                nested_result->insert_default();
380
3
            } else {
381
2
                nested_result->insert_from(*col_result, result_row++);
382
2
            }
383
5
        }
384
385
1
        block.replace_by_position(result, ColumnNullable::create(std::move(nested_result),
386
1
                                                                 std::move(result_null_map)));
387
1
        return Status::OK();
388
2
    }
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_14FunctionAIMaskEE7executeEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjmRKNS_10AIResourceERSt10shared_ptrINS_9AIAdapterEE
_ZNK5doris10AIFunctionINS_20FunctionAISimilarityEE7executeEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjmRKNS_10AIResourceERSt10shared_ptrINS_9AIAdapterEE
Line
Count
Source
269
22
                   std::shared_ptr<AIAdapter>& adapter) const {
270
22
        Columns prompt_columns;
271
22
        prompt_columns.reserve(arguments.size() - 1);
272
22
        ColumnUInt8::MutablePtr result_null_map;
273
66
        for (size_t i = 1; i < arguments.size(); ++i) {
274
44
            const auto& argument = block.get_by_position(arguments[i]);
275
44
            if (argument.type->is_nullable()) {
276
2
                const auto& [column, is_const] = unpack_if_const(argument.column);
277
2
                const auto& nullable =
278
2
                        assert_cast<const ColumnNullable&, TypeCheckOnRelease::DISABLE>(*column);
279
2
                if (!result_null_map) {
280
1
                    result_null_map = ColumnUInt8::create(input_rows_count, 0);
281
1
                }
282
2
                VectorizedUtils::update_null_map(result_null_map->get_data(),
283
2
                                                 nullable.get_null_map_data(), is_const);
284
2
            }
285
44
            prompt_columns.emplace_back(
286
44
                    argument.unnest_nullable(argument.type->is_nullable()
287
44
                                                     ? argument.get_nullable_column_info()
288
44
                                                     : NullableColumnInfo {},
289
44
                                             false)
290
44
                            .column);
291
44
        }
292
293
22
        if (result_null_map &&
294
22
            !simd::contain_zero(result_null_map->get_data().data(), input_rows_count)) {
295
0
            block.get_by_position(result).column =
296
0
                    block.get_by_position(result).type->create_column_const(input_rows_count,
297
0
                                                                            Field());
298
0
            return Status::OK();
299
0
        }
300
301
22
        auto col_result = assert_cast<const Derived&>(*this).create_result_column();
302
22
        std::vector<std::string> batch_prompts;
303
22
        size_t current_batch_size = 2; // []
304
22
        const size_t max_batch_prompt_size =
305
22
                static_cast<size_t>(get_ai_context_window_size(context));
306
22
        const NullMap* null_map = result_null_map ? &result_null_map->get_data() : nullptr;
307
308
49
        for (size_t i = 0; i < input_rows_count; ++i) {
309
27
            if (null_map && (*null_map)[i]) {
310
2
                continue;
311
2
            }
312
313
25
            std::string prompt;
314
25
            RETURN_IF_ERROR(
315
25
                    assert_cast<const Derived&>(*this).build_prompt(prompt_columns, i, prompt));
316
317
25
            size_t entry_size = estimate_batch_entry_size(batch_prompts.size(), prompt);
318
25
            if (entry_size > max_batch_prompt_size) {
319
0
                if (!batch_prompts.empty()) {
320
0
                    std::vector<std::string> batch_results;
321
0
                    RETURN_IF_ERROR(this->execute_batch_request(batch_prompts, batch_results,
322
0
                                                                config, adapter, context));
323
0
                    RETURN_IF_ERROR(assert_cast<const Derived&>(*this).append_batch_results(
324
0
                            batch_results, *col_result));
325
0
                    batch_prompts.clear();
326
0
                    current_batch_size = 2;
327
0
                }
328
329
0
                std::vector<std::string> single_prompts;
330
0
                single_prompts.emplace_back(std::move(prompt));
331
0
                std::vector<std::string> single_results;
332
0
                RETURN_IF_ERROR(this->execute_batch_request(single_prompts, single_results, config,
333
0
                                                            adapter, context));
334
0
                RETURN_IF_ERROR(assert_cast<const Derived&>(*this).append_batch_results(
335
0
                        single_results, *col_result));
336
0
                continue;
337
0
            }
338
339
25
            size_t additional_size = entry_size + (batch_prompts.empty() ? 0 : 1);
340
25
            if (!batch_prompts.empty() &&
341
25
                current_batch_size + additional_size > max_batch_prompt_size) {
342
0
                std::vector<std::string> batch_results;
343
0
                RETURN_IF_ERROR(this->execute_batch_request(batch_prompts, batch_results, config,
344
0
                                                            adapter, context));
345
0
                RETURN_IF_ERROR(assert_cast<const Derived&>(*this).append_batch_results(
346
0
                        batch_results, *col_result));
347
0
                batch_prompts.clear();
348
0
                current_batch_size = 2;
349
0
                additional_size = entry_size;
350
0
            }
351
352
25
            batch_prompts.emplace_back(std::move(prompt));
353
25
            current_batch_size += additional_size;
354
25
        }
355
356
22
        if (!batch_prompts.empty()) {
357
22
            std::vector<std::string> batch_results;
358
22
            RETURN_IF_ERROR(this->execute_batch_request(batch_prompts, batch_results, config,
359
22
                                                        adapter, context));
360
22
            RETURN_IF_ERROR(assert_cast<const Derived&>(*this).append_batch_results(batch_results,
361
22
                                                                                    *col_result));
362
22
        }
363
364
16
        if (!result_null_map) {
365
15
            block.replace_by_position(result, std::move(col_result));
366
15
            return Status::OK();
367
15
        }
368
369
1
        if (!simd::contain_one(result_null_map->get_data().data(), input_rows_count)) {
370
0
            block.replace_by_position(result, ColumnNullable::create(std::move(col_result),
371
0
                                                                     std::move(result_null_map)));
372
0
            return Status::OK();
373
0
        }
374
375
1
        auto nested_result = col_result->clone_empty();
376
1
        size_t result_row = 0;
377
4
        for (UInt8 is_null : result_null_map->get_data()) {
378
4
            if (is_null) {
379
2
                nested_result->insert_default();
380
2
            } else {
381
2
                nested_result->insert_from(*col_result, result_row++);
382
2
            }
383
4
        }
384
385
1
        block.replace_by_position(result, ColumnNullable::create(std::move(nested_result),
386
1
                                                                 std::move(result_null_map)));
387
1
        return Status::OK();
388
1
    }
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_19FunctionAITranslateEE7executeEPNS_15FunctionContextERNS_5BlockERKSt6vectorIjSaIjEEjmRKNS_10AIResourceERSt10shared_ptrINS_9AIAdapterEE
389
390
private:
391
    // The ai resource must be literal
392
    Status _init_from_resource(FunctionContext* context, const Block& block,
393
                               const ColumnNumbers& arguments, AIResource& config,
394
91
                               std::shared_ptr<AIAdapter>& adapter) const {
395
91
        const ColumnWithTypeAndName& resource_column = block.get_by_position(arguments[0]);
396
91
        StringRef resource_name_ref = resource_column.column->get_data_at(0);
397
91
        std::string resource_name = std::string(resource_name_ref.data, resource_name_ref.size);
398
399
91
        const std::shared_ptr<std::map<std::string, TAIResource>>& ai_resources =
400
91
                context->state()->get_query_ctx()->get_ai_resources();
401
91
        DORIS_CHECK(ai_resources);
402
91
        auto it = ai_resources->find(resource_name);
403
91
        DORIS_CHECK(it != ai_resources->end());
404
91
        PrimitiveType input_type = INVALID_TYPE;
405
91
        if (arguments.size() > 1) {
406
90
            input_type =
407
90
                    remove_nullable(block.get_by_position(arguments[1]).type)->get_primitive_type();
408
90
        }
409
91
        config = assert_cast<const Derived&>(*this).select_ai_resource(it->second, input_type);
410
411
91
        normalize_endpoint(config);
412
413
91
        adapter = AIAdapterFactory::create_adapter(config.provider_type);
414
91
        DORIS_CHECK(adapter);
415
416
91
        adapter->init(config);
417
91
        return Status::OK();
418
91
    }
_ZNK5doris10AIFunctionINS_13FunctionEmbedEE19_init_from_resourceEPNS_15FunctionContextERKNS_5BlockERKSt6vectorIjSaIjEERNS_10AIResourceERSt10shared_ptrINS_9AIAdapterEE
Line
Count
Source
394
15
                               std::shared_ptr<AIAdapter>& adapter) const {
395
15
        const ColumnWithTypeAndName& resource_column = block.get_by_position(arguments[0]);
396
15
        StringRef resource_name_ref = resource_column.column->get_data_at(0);
397
15
        std::string resource_name = std::string(resource_name_ref.data, resource_name_ref.size);
398
399
15
        const std::shared_ptr<std::map<std::string, TAIResource>>& ai_resources =
400
15
                context->state()->get_query_ctx()->get_ai_resources();
401
15
        DORIS_CHECK(ai_resources);
402
15
        auto it = ai_resources->find(resource_name);
403
15
        DORIS_CHECK(it != ai_resources->end());
404
15
        PrimitiveType input_type = INVALID_TYPE;
405
15
        if (arguments.size() > 1) {
406
14
            input_type =
407
14
                    remove_nullable(block.get_by_position(arguments[1]).type)->get_primitive_type();
408
14
        }
409
15
        config = assert_cast<const Derived&>(*this).select_ai_resource(it->second, input_type);
410
411
15
        normalize_endpoint(config);
412
413
15
        adapter = AIAdapterFactory::create_adapter(config.provider_type);
414
15
        DORIS_CHECK(adapter);
415
416
15
        adapter->init(config);
417
15
        return Status::OK();
418
15
    }
_ZNK5doris10AIFunctionINS_16FunctionAIFilterEE19_init_from_resourceEPNS_15FunctionContextERKNS_5BlockERKSt6vectorIjSaIjEERNS_10AIResourceERSt10shared_ptrINS_9AIAdapterEE
Line
Count
Source
394
47
                               std::shared_ptr<AIAdapter>& adapter) const {
395
47
        const ColumnWithTypeAndName& resource_column = block.get_by_position(arguments[0]);
396
47
        StringRef resource_name_ref = resource_column.column->get_data_at(0);
397
47
        std::string resource_name = std::string(resource_name_ref.data, resource_name_ref.size);
398
399
47
        const std::shared_ptr<std::map<std::string, TAIResource>>& ai_resources =
400
47
                context->state()->get_query_ctx()->get_ai_resources();
401
47
        DORIS_CHECK(ai_resources);
402
47
        auto it = ai_resources->find(resource_name);
403
47
        DORIS_CHECK(it != ai_resources->end());
404
47
        PrimitiveType input_type = INVALID_TYPE;
405
47
        if (arguments.size() > 1) {
406
47
            input_type =
407
47
                    remove_nullable(block.get_by_position(arguments[1]).type)->get_primitive_type();
408
47
        }
409
47
        config = assert_cast<const Derived&>(*this).select_ai_resource(it->second, input_type);
410
411
47
        normalize_endpoint(config);
412
413
47
        adapter = AIAdapterFactory::create_adapter(config.provider_type);
414
47
        DORIS_CHECK(adapter);
415
416
47
        adapter->init(config);
417
47
        return Status::OK();
418
47
    }
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_20FunctionAIFixGrammarEE19_init_from_resourceEPNS_15FunctionContextERKNS_5BlockERKSt6vectorIjSaIjEERNS_10AIResourceERSt10shared_ptrINS_9AIAdapterEE
_ZNK5doris10AIFunctionINS_19FunctionAISentimentEE19_init_from_resourceEPNS_15FunctionContextERKNS_5BlockERKSt6vectorIjSaIjEERNS_10AIResourceERSt10shared_ptrINS_9AIAdapterEE
Line
Count
Source
394
2
                               std::shared_ptr<AIAdapter>& adapter) const {
395
2
        const ColumnWithTypeAndName& resource_column = block.get_by_position(arguments[0]);
396
2
        StringRef resource_name_ref = resource_column.column->get_data_at(0);
397
2
        std::string resource_name = std::string(resource_name_ref.data, resource_name_ref.size);
398
399
2
        const std::shared_ptr<std::map<std::string, TAIResource>>& ai_resources =
400
2
                context->state()->get_query_ctx()->get_ai_resources();
401
2
        DORIS_CHECK(ai_resources);
402
2
        auto it = ai_resources->find(resource_name);
403
2
        DORIS_CHECK(it != ai_resources->end());
404
2
        PrimitiveType input_type = INVALID_TYPE;
405
2
        if (arguments.size() > 1) {
406
2
            input_type =
407
2
                    remove_nullable(block.get_by_position(arguments[1]).type)->get_primitive_type();
408
2
        }
409
2
        config = assert_cast<const Derived&>(*this).select_ai_resource(it->second, input_type);
410
411
2
        normalize_endpoint(config);
412
413
2
        adapter = AIAdapterFactory::create_adapter(config.provider_type);
414
2
        DORIS_CHECK(adapter);
415
416
2
        adapter->init(config);
417
2
        return Status::OK();
418
2
    }
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_19FunctionAISummarizeEE19_init_from_resourceEPNS_15FunctionContextERKNS_5BlockERKSt6vectorIjSaIjEERNS_10AIResourceERSt10shared_ptrINS_9AIAdapterEE
_ZNK5doris10AIFunctionINS_18FunctionAIClassifyEE19_init_from_resourceEPNS_15FunctionContextERKNS_5BlockERKSt6vectorIjSaIjEERNS_10AIResourceERSt10shared_ptrINS_9AIAdapterEE
Line
Count
Source
394
2
                               std::shared_ptr<AIAdapter>& adapter) const {
395
2
        const ColumnWithTypeAndName& resource_column = block.get_by_position(arguments[0]);
396
2
        StringRef resource_name_ref = resource_column.column->get_data_at(0);
397
2
        std::string resource_name = std::string(resource_name_ref.data, resource_name_ref.size);
398
399
2
        const std::shared_ptr<std::map<std::string, TAIResource>>& ai_resources =
400
2
                context->state()->get_query_ctx()->get_ai_resources();
401
2
        DORIS_CHECK(ai_resources);
402
2
        auto it = ai_resources->find(resource_name);
403
2
        DORIS_CHECK(it != ai_resources->end());
404
2
        PrimitiveType input_type = INVALID_TYPE;
405
2
        if (arguments.size() > 1) {
406
2
            input_type =
407
2
                    remove_nullable(block.get_by_position(arguments[1]).type)->get_primitive_type();
408
2
        }
409
2
        config = assert_cast<const Derived&>(*this).select_ai_resource(it->second, input_type);
410
411
2
        normalize_endpoint(config);
412
413
2
        adapter = AIAdapterFactory::create_adapter(config.provider_type);
414
2
        DORIS_CHECK(adapter);
415
416
2
        adapter->init(config);
417
2
        return Status::OK();
418
2
    }
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_17FunctionAIExtractEE19_init_from_resourceEPNS_15FunctionContextERKNS_5BlockERKSt6vectorIjSaIjEERNS_10AIResourceERSt10shared_ptrINS_9AIAdapterEE
_ZNK5doris10AIFunctionINS_18FunctionAIGenerateEE19_init_from_resourceEPNS_15FunctionContextERKNS_5BlockERKSt6vectorIjSaIjEERNS_10AIResourceERSt10shared_ptrINS_9AIAdapterEE
Line
Count
Source
394
3
                               std::shared_ptr<AIAdapter>& adapter) const {
395
3
        const ColumnWithTypeAndName& resource_column = block.get_by_position(arguments[0]);
396
3
        StringRef resource_name_ref = resource_column.column->get_data_at(0);
397
3
        std::string resource_name = std::string(resource_name_ref.data, resource_name_ref.size);
398
399
3
        const std::shared_ptr<std::map<std::string, TAIResource>>& ai_resources =
400
3
                context->state()->get_query_ctx()->get_ai_resources();
401
3
        DORIS_CHECK(ai_resources);
402
3
        auto it = ai_resources->find(resource_name);
403
3
        DORIS_CHECK(it != ai_resources->end());
404
3
        PrimitiveType input_type = INVALID_TYPE;
405
3
        if (arguments.size() > 1) {
406
3
            input_type =
407
3
                    remove_nullable(block.get_by_position(arguments[1]).type)->get_primitive_type();
408
3
        }
409
3
        config = assert_cast<const Derived&>(*this).select_ai_resource(it->second, input_type);
410
411
3
        normalize_endpoint(config);
412
413
3
        adapter = AIAdapterFactory::create_adapter(config.provider_type);
414
3
        DORIS_CHECK(adapter);
415
416
3
        adapter->init(config);
417
3
        return Status::OK();
418
3
    }
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_14FunctionAIMaskEE19_init_from_resourceEPNS_15FunctionContextERKNS_5BlockERKSt6vectorIjSaIjEERNS_10AIResourceERSt10shared_ptrINS_9AIAdapterEE
_ZNK5doris10AIFunctionINS_20FunctionAISimilarityEE19_init_from_resourceEPNS_15FunctionContextERKNS_5BlockERKSt6vectorIjSaIjEERNS_10AIResourceERSt10shared_ptrINS_9AIAdapterEE
Line
Count
Source
394
22
                               std::shared_ptr<AIAdapter>& adapter) const {
395
22
        const ColumnWithTypeAndName& resource_column = block.get_by_position(arguments[0]);
396
22
        StringRef resource_name_ref = resource_column.column->get_data_at(0);
397
22
        std::string resource_name = std::string(resource_name_ref.data, resource_name_ref.size);
398
399
22
        const std::shared_ptr<std::map<std::string, TAIResource>>& ai_resources =
400
22
                context->state()->get_query_ctx()->get_ai_resources();
401
22
        DORIS_CHECK(ai_resources);
402
22
        auto it = ai_resources->find(resource_name);
403
22
        DORIS_CHECK(it != ai_resources->end());
404
22
        PrimitiveType input_type = INVALID_TYPE;
405
22
        if (arguments.size() > 1) {
406
22
            input_type =
407
22
                    remove_nullable(block.get_by_position(arguments[1]).type)->get_primitive_type();
408
22
        }
409
22
        config = assert_cast<const Derived&>(*this).select_ai_resource(it->second, input_type);
410
411
22
        normalize_endpoint(config);
412
413
22
        adapter = AIAdapterFactory::create_adapter(config.provider_type);
414
22
        DORIS_CHECK(adapter);
415
416
22
        adapter->init(config);
417
22
        return Status::OK();
418
22
    }
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_19FunctionAITranslateEE19_init_from_resourceEPNS_15FunctionContextERKNS_5BlockERKSt6vectorIjSaIjEERNS_10AIResourceERSt10shared_ptrINS_9AIAdapterEE
419
420
76
    AIResource select_ai_resource(const TAIResource& resource, PrimitiveType /*input_type*/) const {
421
76
        return AIResource(resource);
422
76
    }
_ZNK5doris10AIFunctionINS_16FunctionAIFilterEE18select_ai_resourceERKNS_11TAIResourceENS_13PrimitiveTypeE
Line
Count
Source
420
47
    AIResource select_ai_resource(const TAIResource& resource, PrimitiveType /*input_type*/) const {
421
47
        return AIResource(resource);
422
47
    }
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_20FunctionAIFixGrammarEE18select_ai_resourceERKNS_11TAIResourceENS_13PrimitiveTypeE
_ZNK5doris10AIFunctionINS_19FunctionAISentimentEE18select_ai_resourceERKNS_11TAIResourceENS_13PrimitiveTypeE
Line
Count
Source
420
2
    AIResource select_ai_resource(const TAIResource& resource, PrimitiveType /*input_type*/) const {
421
2
        return AIResource(resource);
422
2
    }
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_19FunctionAISummarizeEE18select_ai_resourceERKNS_11TAIResourceENS_13PrimitiveTypeE
_ZNK5doris10AIFunctionINS_18FunctionAIClassifyEE18select_ai_resourceERKNS_11TAIResourceENS_13PrimitiveTypeE
Line
Count
Source
420
2
    AIResource select_ai_resource(const TAIResource& resource, PrimitiveType /*input_type*/) const {
421
2
        return AIResource(resource);
422
2
    }
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_17FunctionAIExtractEE18select_ai_resourceERKNS_11TAIResourceENS_13PrimitiveTypeE
_ZNK5doris10AIFunctionINS_18FunctionAIGenerateEE18select_ai_resourceERKNS_11TAIResourceENS_13PrimitiveTypeE
Line
Count
Source
420
3
    AIResource select_ai_resource(const TAIResource& resource, PrimitiveType /*input_type*/) const {
421
3
        return AIResource(resource);
422
3
    }
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_14FunctionAIMaskEE18select_ai_resourceERKNS_11TAIResourceENS_13PrimitiveTypeE
_ZNK5doris10AIFunctionINS_20FunctionAISimilarityEE18select_ai_resourceERKNS_11TAIResourceENS_13PrimitiveTypeE
Line
Count
Source
420
22
    AIResource select_ai_resource(const TAIResource& resource, PrimitiveType /*input_type*/) const {
421
22
        return AIResource(resource);
422
22
    }
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_19FunctionAITranslateEE18select_ai_resourceERKNS_11TAIResourceENS_13PrimitiveTypeE
423
424
    // Serializes one text batch into the shared JSON-array prompt format consumed by LLM
425
    // providers for batch string functions.
426
    Status build_batch_prompt(const std::vector<std::string>& batch_prompts,
427
10
                              std::string& prompt) const {
428
10
        rapidjson::StringBuffer buffer;
429
10
        rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
430
431
10
        writer.StartArray();
432
20
        for (size_t i = 0; i < batch_prompts.size(); ++i) {
433
10
            writer.StartObject();
434
10
            writer.Key("idx");
435
10
            writer.Uint64(i);
436
10
            writer.Key("input");
437
10
            writer.String(batch_prompts[i].data(),
438
10
                          static_cast<rapidjson::SizeType>(batch_prompts[i].size()));
439
10
            writer.EndObject();
440
10
        }
441
10
        writer.EndArray();
442
443
10
        prompt = buffer.GetString();
444
10
        return Status::OK();
445
10
    }
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_16FunctionAIFilterEE18build_batch_promptERKSt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS9_EERS9_
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_20FunctionAIFixGrammarEE18build_batch_promptERKSt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS9_EERS9_
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_19FunctionAISentimentEE18build_batch_promptERKSt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS9_EERS9_
_ZNK5doris10AIFunctionINS_19FunctionAISummarizeEE18build_batch_promptERKSt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS9_EERS9_
Line
Count
Source
427
10
                              std::string& prompt) const {
428
10
        rapidjson::StringBuffer buffer;
429
10
        rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
430
431
10
        writer.StartArray();
432
20
        for (size_t i = 0; i < batch_prompts.size(); ++i) {
433
10
            writer.StartObject();
434
10
            writer.Key("idx");
435
10
            writer.Uint64(i);
436
10
            writer.Key("input");
437
10
            writer.String(batch_prompts[i].data(),
438
10
                          static_cast<rapidjson::SizeType>(batch_prompts[i].size()));
439
10
            writer.EndObject();
440
10
        }
441
10
        writer.EndArray();
442
443
10
        prompt = buffer.GetString();
444
10
        return Status::OK();
445
10
    }
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_18FunctionAIClassifyEE18build_batch_promptERKSt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS9_EERS9_
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_17FunctionAIExtractEE18build_batch_promptERKSt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS9_EERS9_
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_18FunctionAIGenerateEE18build_batch_promptERKSt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS9_EERS9_
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_14FunctionAIMaskEE18build_batch_promptERKSt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS9_EERS9_
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_20FunctionAISimilarityEE18build_batch_promptERKSt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS9_EERS9_
Unexecuted instantiation: _ZNK5doris10AIFunctionINS_19FunctionAITranslateEE18build_batch_promptERKSt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS9_EERS9_
446
};
447
448
} // namespace doris