HappenLee commented on PR #67673:
URL: https://github.com/apache/doris/pull/67673#issuecomment-5651329512

   Reviewed commit `83a2ac73e5e5469ea3f1c83cafc31dbbb61dd89c`. The dedicated 
embedding selection is straightforward, but I think the following resource 
validation and consistency issues need to be addressed.
   
   1. **[P1] Keep the resource validated during analysis consistent with the 
resource sent to BE.**
   
      The new general-group check validates one resource object, but the 
statement records only its name. A possible interleaving is: an `AI_AGG` query 
passes analysis against a resource with a complete general group; another 
session drops that resource and creates a valid embed-only resource with the 
same name; `Coordinator.getNeededAiResources()` or 
`ThriftPlansBuilder.collectAiResources()` then looks up the replacement and 
checks only its type. BE receives an empty general provider, and 
`AggregateFunctionAIAggData::prepare()` dereferences the null adapter returned 
by the factory. This is a less common concurrency scenario, but it is a direct 
null dereference, including in Release builds.
   
      Please retain the validated resource snapshot in the statement, or 
revalidate the required capabilities and obtain the same snapshot at transport 
time. Add a DROP/CREATE interleaving test. Taking a read lock only inside 
`toThrift()` would not address the identity change.
   
      References: [analysis 
check](https://github.com/apache/doris/blob/83a2ac73e5e5469ea3f1c83cafc31dbbb61dd89c/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/AIAgg.java#L90-L99),
 [transport 
lookup](https://github.com/apache/doris/blob/83a2ac73e5e5469ea3f1c83cafc31dbbb61dd89c/fe/fe-core/src/main/java/org/apache/doris/qe/runtime/ThriftPlansBuilder.java#L222-L240),
 [BE 
initialization](https://github.com/apache/doris/blob/83a2ac73e5e5469ea3f1c83cafc31dbbb61dd89c/be/src/exprs/aggregate/aggregate_function_ai_agg.h#L131-L156).
   
   2. **[P2] Persist the normalized provider produced by ALTER validation.**
   
      `requiredAIProperties(changedProperties)` normalizes the provider in a 
temporary merged map, but `modifyProperties()` subsequently writes the original 
ALTER map. Consequently, lowercase `openai` passes validation but is persisted 
and forwarded unchanged. The BE adapter factory is case-sensitive and cannot 
resolve it.
   
      Concrete input:
   
      ```sql
      CREATE RESOURCE 'review_embed_case' PROPERTIES (
        'type'='ai',
        'ai.embed.provider_type'='OPENAI',
        'ai.embed.endpoint'='https://example.com/v1/embeddings',
        'ai.embed.model_name'='embedding-model',
        'ai.embed.api_key'='dummy-key',
        'ai.dimensions'='8'
      );
      ALTER RESOURCE 'review_embed_case' PROPERTIES (
        'ai.embed.provider_type'='openai'
      );
      SELECT EMBED('review_embed_case', 'hello');
      ```
   
      Positive dimensions intentionally avoid the pre-existing 
default-dimensions validation issue. Please install the validated and 
normalized merged snapshot, and cover ALTER plus persistence/replay and 
`toThrift()` in tests.
   
      References: 
[normalization](https://github.com/apache/doris/blob/83a2ac73e5e5469ea3f1c83cafc31dbbb61dd89c/fe/fe-core/src/main/java/org/apache/doris/datasource/property/constants/AIProperties.java#L112-L128),
 [ALTER 
implementation](https://github.com/apache/doris/blob/83a2ac73e5e5469ea3f1c83cafc31dbbb61dd89c/fe/fe-core/src/main/java/org/apache/doris/catalog/AIResource.java#L128-L148).
   
   3. **[P2] Validate group completeness on ALTER regardless of 
`ai.validity_check` or LOCAL.**
   
      When the general provider is LOCAL, or `ai.validity_check=false`, ALTER 
skips `requiredAIProperties()`. It can therefore persist only 
`ai.embed.endpoint`. The new selector treats any dedicated field as sufficient 
to select the entire dedicated group, resulting in an empty provider and a 
failed adapter invariant.
   
      ```sql
      CREATE RESOURCE 'review_embed_partial' PROPERTIES (
        'type'='ai',
        'ai.provider_type'='LOCAL',
        'ai.endpoint'='http://localhost:8000/v1/embeddings',
        'ai.model_name'='local-model'
      );
      ALTER RESOURCE 'review_embed_partial' PROPERTIES (
        'ai.embed.endpoint'='http://localhost:8001/v1/embeddings'
      );
      SELECT EMBED('review_embed_partial', 'hello');
      ```
   
      This fails before an HTTP request is made. Please separate mandatory 
structural validation from optional validity checking and reject partial groups 
during ALTER. Silently falling back to another model would hide the invalid 
configuration. The ALTER framework predates this PR, but the new 
group-selection logic relies on an invariant that this framework does not 
guarantee.
   
      References: [conditional 
validation](https://github.com/apache/doris/blob/83a2ac73e5e5469ea3f1c83cafc31dbbb61dd89c/fe/fe-core/src/main/java/org/apache/doris/catalog/AIResource.java#L107-L132),
 [dedicated-group 
selector](https://github.com/apache/doris/blob/83a2ac73e5e5469ea3f1c83cafc31dbbb61dd89c/be/src/exprs/function/ai/embed.h#L47-L51).
   
   4. **[P2] Serialize a consistent resource snapshot under the resource read 
lock.**
   
      ALTER mutates `properties` under `writeLock()`, but `toThrift()` takes no 
read lock, and both transport callers invoke it directly. Even a completely 
valid ALTER can produce this interleaving:
   
      ```text
      Query: check embed_provider_type -> absent; skip it
      ALTER: install a complete dedicated group and finish
      Query: read embed_endpoint, embed_api_key, embed_model_name -> present
      BE: select the dedicated group, but its provider is empty
      ```
   
      Please copy the properties under `readLock()` and serialize that 
snapshot. The merged ALTER state should also be validated and installed within 
one write-locked transition: two requests validating the same old OPENAI/key 
state can otherwise commit LOCAL/empty-key followed by GEMINI, leaving GEMINI 
without a key. Add deterministic interleaving tests for both cases.
   
      Reference: [unlocked 
serialization](https://github.com/apache/doris/blob/83a2ac73e5e5469ea3f1c83cafc31dbbb61dd89c/fe/fe-core/src/main/java/org/apache/doris/catalog/AIResource.java#L173-L201).
   
   5. **[P2] Validate dedicated providers against embedding capabilities.**
   
      The dedicated group uses the general provider allowlist, so an embed-only 
resource with DEEPSEEK or MOONSHOT passes CREATE and expression analysis. 
However, both corresponding BE adapters unconditionally return `NotSupported` 
for embedding construction and parsing. Such a resource cannot execute EMBED 
even with an otherwise usable endpoint.
   
      Please reject explicitly unsupported providers for the dedicated group 
and add negative tests. A small shared capability description would be 
sufficient.
   
      References: [group 
validation](https://github.com/apache/doris/blob/83a2ac73e5e5469ea3f1c83cafc31dbbb61dd89c/fe/fe-core/src/main/java/org/apache/doris/datasource/property/constants/AIProperties.java#L63-L80),
 [unsupported 
adapters](https://github.com/apache/doris/blob/83a2ac73e5e5469ea3f1c83cafc31dbbb61dd89c/be/src/exprs/function/ai/ai_adapter.h#L1016-L1040).
   
   For findings 2–4, the EMBED path reaches `DORIS_CHECK(adapter)`: Release 
builds convert this to a query error, while Debug/ASAN builds terminate through 
`Status::FatalError()`. These should not all be described as production BE 
crashes. Finding 1's `AI_AGG` null dereference is a separate failure path.
   
   From a reuse and scope perspective, I would keep the single 
configuration-selection hook and make CREATE/ALTER share the validated snapshot 
logic. I would also split `ai.effort` into a separate PR: it is independent of 
embedding routing and additionally changes provider payloads, aggregate-state 
serialization, and the execution version. The current effort version gate and 
empty-value clearing fix are present; I am not reporting those as unresolved 
issues. The PR description and release note should reflect the final scope.
   
   Validation: the existing `AIResourceTest` (20 tests) and 
`RepositoryAuditEncryptionTest` (5 tests) passed locally, as did changed-file 
clang-format 16.0.6, build hygiene, and diff checks. The failure scenarios 
above are based on source tracing and concrete inputs/interleavings; I did not 
run them against a live FE/BE cluster. The existing tests do not cover these 
ALTER/concurrency cases. I did not identify an obvious new per-row performance 
regression; no benchmark was run.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to