private Model importProfile(RankProfilesConfig.Rankprofile profile,
                                RankingConstantsConfig constantsConfig,
                                RankingExpressionsConfig expressionsConfig,
                                OnnxModelsConfig onnxModelsConfig)
            throws ParseException {

        List<OnnxModel> onnxModels = readOnnxModelsConfig(onnxModelsConfig);
        List<Constant> constants = readLargeConstants(constantsConfig);
        Map<String, RankingExpression> largeExpressions = readLargeExpressions(expressionsConfig);

        Map<FunctionReference, ExpressionFunction> functions = new LinkedHashMap<>();
        Map<FunctionReference, ExpressionFunction> referencedFunctions = new LinkedHashMap<>();
        SmallConstantsInfo smallConstantsInfo = new SmallConstantsInfo();
        ExpressionFunction firstPhase = null;
        ExpressionFunction secondPhase = null;
        ExpressionFunction globalPhase = null;
        Map<String, TensorType> declaredTypes = new LinkedHashMap<>();
        Set<String> matchFeaturesSet = new HashSet<>();
        for (RankProfilesConfig.Rankprofile.Fef.Property property : profile.fef().property()) {
            Optional<FunctionReference> reference = FunctionReference.fromSerial(property.name());
            Optional<FunctionReference> externalReference = FunctionReference.fromExternalSerial(property.name());
            Optional<Pair<FunctionReference, String>> argumentType = FunctionReference.fromTypeArgumentSerial(property.name());
            Optional<FunctionReference> returnType = FunctionReference.fromReturnTypeSerial(property.name());
            Optional<String> typeDeclaredFeature = fromTypeDeclarationSerial(property.name());
            if (externalReference.isPresent()) {
                RankingExpression expression = largeExpressions.get(property.value());
                ExpressionFunction function = new ExpressionFunction(externalReference.get().functionName(),
                        List.of(),
                        expression);

                if (externalReference.get().isFree()) // make available in model under configured name
                    functions.put(externalReference.get(), function);
                // Make all functions, bound or not, available under the name they are referenced by in expressions
                referencedFunctions.put(externalReference.get(), function);
            }
            else if (reference.isPresent()) {
                RankingExpression expression = new RankingExpression(reference.get().functionName(), property.value());
                ExpressionFunction function = new ExpressionFunction(reference.get().functionName(),
                                                                     List.of(),
                                                                     expression);

                if (reference.get().isFree()) // make available in model under configured name
                    functions.put(reference.get(), function);
                // Make all functions, bound or not, available under the name they are referenced by in expressions
                referencedFunctions.put(reference.get(), function);
            }
            else if (argumentType.isPresent()) { // Arguments always follows the function in properties
                FunctionReference argReference = argumentType.get().getFirst();
                ExpressionFunction function = referencedFunctions.get(argReference);
                function = function.withArgument(argumentType.get().getSecond(), TensorType.fromSpec(property.value()));
                if (argReference.isFree())
                    functions.put(argReference, function);
                referencedFunctions.put(argReference, function);
            }
            else if (returnType.isPresent()) { // Return type always follows the function in properties
                FunctionReference functionRef = returnType.get();
                ExpressionFunction function = referencedFunctions.get(functionRef);
                TensorType type = TensorType.fromSpec(property.value());
                function = function.withReturnType(type);
                if (functionRef.isFree())
                    functions.put(functionRef, function);
                referencedFunctions.put(functionRef, function);
                declaredTypes.put(function.getName(), type); // "foo"
                declaredTypes.put(functionRef.serialForm(), type); // "rankingExpression(foo)"
            }
            else if (property.name().equals("vespa.match.feature")) {
                matchFeaturesSet.add(property.value());
            }
            else if (property.name().equals("vespa.rank.firstphase")) { // Include in addition to functions
                firstPhase = new ExpressionFunction("firstphase", new ArrayList<>(),
                                                    new RankingExpression("first-phase", property.value()));
            }
            else if (property.name().equals("vespa.rank.secondphase")) { // Include in addition to functions
                secondPhase = new ExpressionFunction("secondphase", new ArrayList<>(),
                                                     new RankingExpression("second-phase", property.value()));
            }
            else if (property.name().equals("vespa.rank.globalphase")) { // Include in addition to functions
                globalPhase = new ExpressionFunction("globalphase", new ArrayList<>(),
                                                     new RankingExpression("global-phase", property.value()));
            }
            else if (typeDeclaredFeature.isPresent()) {
                declaredTypes.put(typeDeclaredFeature.get(), TensorType.fromSpec(property.value()));
            }
            else {
                smallConstantsInfo.addIfSmallConstantInfo(property.name(), property.value());
            }
        }
        if (functionByName("firstphase", functions.values()) == null && firstPhase != null) // may be already included, depending on body
            functions.put(FunctionReference.fromName("firstphase"), firstPhase);
        if (functionByName("secondphase", functions.values()) == null && secondPhase != null) // may be already included, depending on body
            functions.put(FunctionReference.fromName("secondphase"), secondPhase);
        if (functionByName("globalphase", functions.values()) == null && globalPhase != null) // may be already included, depending on body
            functions.put(FunctionReference.fromName("globalphase"), globalPhase);

        constants.addAll(smallConstantsInfo.asConstants());
        for (String k : matchFeaturesSet) {
            var optRef = FunctionReference.fromSerial(k);
            var ref = optRef.orElse(FunctionReference.fromName(k));
            referencedFunctions.remove(ref);
        }
        try {
            return new Model(profile.name(), functions, referencedFunctions, declaredTypes, constants, onnxModels);
        }
        catch (RuntimeException e) {
            throw new IllegalArgumentException("Could not load model '" + profile.name() + "'", e);
        }
    }
Returns a map of the models contained in this config, indexed on name.
The map is modifiable and owned by the caller.
model-evaluation/src/main/java/ai/vespa/models/evaluation/RankProfilesConfigImporter.java