Skip to content

Commit dfe3506

Browse files
Merge branch 'main' into get-desired-balance-node-weights
2 parents 72635ca + b9573b3 commit dfe3506

File tree

24 files changed

+943
-120
lines changed

24 files changed

+943
-120
lines changed

docs/changelog/131531.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
pr: 131531
2+
summary: Integrate LIKE/RLIKE LIST with `ReplaceStringCasingWithInsensitiveRegexMatch`
3+
rule
4+
area: ES|QL
5+
type: enhancement
6+
issues: []
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
## `COMPLETION` [esql-completion]
2+
3+
```yaml {applies_to}
4+
serverless: preview
5+
stack: preview 9.1.0
6+
```
7+
8+
The `COMPLETION` command allows you to send prompts and context to a Large Language Model (LLM) directly within your ES|QL queries, to perform text generation tasks.
9+
10+
**Syntax**
11+
12+
```esql
13+
COMPLETION [column =] prompt WITH inference_id
14+
```
15+
16+
**Parameters**
17+
18+
`column`
19+
: (Optional) The name of the output column containing the LLM's response.
20+
If not specified, the results will be stored in a column named `completion`.
21+
If the specified column already exists, it will be overwritten with the new results.
22+
23+
`prompt`
24+
: The input text or expression used to prompt the LLM.
25+
This can be a string literal or a reference to a column containing text.
26+
27+
`inference_id`
28+
: The ID of the [inference endpoint](docs-content://explore-analyze/elastic-inference/inference-api.md) to use for the task.
29+
The inference endpoint must be configured with the `completion` task type.
30+
31+
**Description**
32+
33+
The `COMPLETION` command provides a general-purpose interface for
34+
text generation tasks using a Large Language Model (LLM) in ES|QL.
35+
36+
`COMPLETION` supports a wide range of text generation tasks. Depending on your
37+
prompt and the model you use, you can perform arbitrary text generation tasks
38+
including:
39+
40+
- Question answering
41+
- Summarization
42+
- Translation
43+
- Content rewriting
44+
- Creative generation
45+
46+
**Requirements**
47+
48+
To use this command, you must deploy your LLM model in Elasticsearch as
49+
an [≈inference endpoint](https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-inference-put) with the
50+
task type `completion`.
51+
52+
**Examples**
53+
54+
Use the default column name (results stored in `completion` column):
55+
56+
```esql
57+
ROW question = "What is Elasticsearch?"
58+
| COMPLETION question WITH test_completion_model
59+
| KEEP question, completion
60+
```
61+
62+
| question:keyword | completion:keyword |
63+
|------------------------|-------------------------------------------|
64+
| What is Elasticsearch? | A distributed search and analytics engine |
65+
66+
Specify the output column (results stored in `answer` column):
67+
68+
```esql
69+
ROW question = "What is Elasticsearch?"
70+
| COMPLETION answer = question WITH test_completion_model
71+
| KEEP question, answer
72+
```
73+
74+
| question:keyword | answer:keyword |
75+
| --- | --- |
76+
| What is Elasticsearch? | A distributed search and analytics engine |
77+
78+
Summarize the top 10 highest-rated movies using a prompt:
79+
80+
```esql
81+
FROM movies
82+
| SORT rating DESC
83+
| LIMIT 10
84+
| EVAL prompt = CONCAT(
85+
"Summarize this movie using the following information: \n",
86+
"Title: ", title, "\n",
87+
"Synopsis: ", synopsis, "\n",
88+
"Actors: ", MV_CONCAT(actors, ", "), "\n",
89+
)
90+
| COMPLETION summary = prompt WITH test_completion_model
91+
| KEEP title, summary, rating
92+
```
93+
94+
95+
| title:keyword | summary:keyword | rating:double |
96+
| --- | --- | --- |
97+
| The Shawshank Redemption | A tale of hope and redemption in prison. | 9.3 |
98+
| The Godfather | A mafia family's rise and fall. | 9.2 |
99+
| The Dark Knight | Batman battles the Joker in Gotham. | 9.0 |
100+
| Pulp Fiction | Interconnected crime stories with dark humor. | 8.9 |
101+
| Fight Club | A man starts an underground fight club. | 8.8 |
102+
| Inception | A thief steals secrets through dreams. | 8.8 |
103+
| The Matrix | A hacker discovers reality is a simulation. | 8.7 |
104+
| Parasite | Class conflict between two families. | 8.6 |
105+
| Interstellar | A team explores space to save humanity. | 8.6 |
106+
| The Prestige | Rival magicians engage in dangerous competition. | 8.5 |

docs/reference/query-languages/esql/_snippets/lists/processing-commands.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
* [preview] [`CHANGE_POINT`](../../commands/processing-commands.md#esql-change_point)
2+
* [preview] [`COMPLETION`](../../commands/processing-commands.md#esql-completion)
23
* [`DISSECT`](../../commands/processing-commands.md#esql-dissect)
34
* [`DROP`](../../commands/processing-commands.md#esql-drop)
45
* [`ENRICH`](../../commands/processing-commands.md#esql-enrich)

docs/reference/query-languages/esql/commands/processing-commands.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ mapped_pages:
2020
:::{include} ../_snippets/commands/layout/change_point.md
2121
:::
2222

23+
:::{include} ../_snippets/commands/layout/completion.md
24+
:::
25+
2326
:::{include} ../_snippets/commands/layout/dissect.md
2427
:::
2528

server/src/main/java/org/elasticsearch/TransportVersions.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,8 @@ static TransportVersion def(int id) {
347347
public static final TransportVersion ML_INFERENCE_LLAMA_ADDED = def(9_125_0_00);
348348
public static final TransportVersion SHARD_WRITE_LOAD_IN_CLUSTER_INFO = def(9_126_0_00);
349349
public static final TransportVersion ESQL_SAMPLE_OPERATOR_STATUS = def(9_127_0_00);
350-
public static final TransportVersion NODE_WEIGHTS_ADDED_TO_NODE_BALANCE_STATS = def(9_128_0_00);
350+
public static final TransportVersion ESQL_TOPN_TIMINGS = def(9_128_0_00);
351+
public static final TransportVersion NODE_WEIGHTS_ADDED_TO_NODE_BALANCE_STATS = def(9_129_0_00);
351352

352353
/*
353354
* STOP! READ THIS FIRST! No, really,

server/src/main/java/org/elasticsearch/index/mapper/KeywordFieldMapper.java

Lines changed: 56 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,8 @@ public static final class Builder extends FieldMapper.DimensionBuilder {
209209
private final IndexAnalyzers indexAnalyzers;
210210
private final ScriptCompiler scriptCompiler;
211211
private final IndexVersion indexCreatedVersion;
212-
private final boolean useDocValuesSkipper;
212+
private final boolean enableDocValuesSkipper;
213+
private final boolean forceDocValuesSkipper;
213214
private final SourceKeepMode indexSourceKeepMode;
214215

215216
public Builder(final String name, final MappingParserContext mappingParserContext) {
@@ -222,6 +223,7 @@ public Builder(final String name, final MappingParserContext mappingParserContex
222223
mappingParserContext.getIndexSettings().getMode(),
223224
mappingParserContext.getIndexSettings().getIndexSortConfig(),
224225
USE_DOC_VALUES_SKIPPER.get(mappingParserContext.getSettings()),
226+
false,
225227
mappingParserContext.getIndexSettings().sourceKeepMode()
226228
);
227229
}
@@ -243,6 +245,7 @@ public Builder(final String name, final MappingParserContext mappingParserContex
243245
IndexMode.STANDARD,
244246
null,
245247
false,
248+
false,
246249
sourceKeepMode
247250
);
248251
}
@@ -255,7 +258,8 @@ private Builder(
255258
IndexVersion indexCreatedVersion,
256259
IndexMode indexMode,
257260
IndexSortConfig indexSortConfig,
258-
boolean useDocValuesSkipper,
261+
boolean enableDocValuesSkipper,
262+
boolean forceDocValuesSkipper,
259263
SourceKeepMode indexSourceKeepMode
260264
) {
261265
super(name);
@@ -293,14 +297,36 @@ private Builder(
293297
});
294298
this.indexSortConfig = indexSortConfig;
295299
this.indexMode = indexMode;
296-
this.useDocValuesSkipper = useDocValuesSkipper;
300+
this.enableDocValuesSkipper = enableDocValuesSkipper;
301+
this.forceDocValuesSkipper = forceDocValuesSkipper;
297302
this.indexSourceKeepMode = indexSourceKeepMode;
298303
}
299304

300305
public Builder(String name, IndexVersion indexCreatedVersion) {
301306
this(name, null, ScriptCompiler.NONE, Integer.MAX_VALUE, indexCreatedVersion, SourceKeepMode.NONE);
302307
}
303308

309+
public static Builder buildWithDocValuesSkipper(
310+
String name,
311+
IndexMode indexMode,
312+
IndexVersion indexCreatedVersion,
313+
boolean enableDocValuesSkipper
314+
) {
315+
return new Builder(
316+
name,
317+
null,
318+
ScriptCompiler.NONE,
319+
Integer.MAX_VALUE,
320+
indexCreatedVersion,
321+
indexMode,
322+
// Sort config is used to decide if DocValueSkippers can be used. Since skippers are forced, a sort config is not needed.
323+
null,
324+
enableDocValuesSkipper,
325+
true,
326+
SourceKeepMode.NONE
327+
);
328+
}
329+
304330
public Builder ignoreAbove(int ignoreAbove) {
305331
this.ignoreAbove.setValue(ignoreAbove);
306332
return this;
@@ -422,7 +448,9 @@ private KeywordFieldType buildFieldType(MapperBuilderContext context, FieldType
422448
@Override
423449
public KeywordFieldMapper build(MapperBuilderContext context) {
424450
FieldType fieldtype = resolveFieldType(
425-
useDocValuesSkipper,
451+
enableDocValuesSkipper,
452+
forceDocValuesSkipper,
453+
hasDocValues,
426454
indexCreatedVersion,
427455
indexSortConfig,
428456
indexMode,
@@ -460,24 +488,30 @@ public KeywordFieldMapper build(MapperBuilderContext context) {
460488
buildFieldType(context, fieldtype),
461489
builderParams(this, context),
462490
context.isSourceSynthetic(),
463-
useDocValuesSkipper,
464491
this,
465492
offsetsFieldName,
466493
indexSourceKeepMode
467494
);
468495
}
469496

470-
private FieldType resolveFieldType(
471-
final boolean useDocValuesSkipper,
497+
private static FieldType resolveFieldType(
498+
final boolean enableDocValuesSkipper,
499+
final boolean forceDocValuesSkipper,
500+
final Parameter<Boolean> hasDocValues,
472501
final IndexVersion indexCreatedVersion,
473502
final IndexSortConfig indexSortConfig,
474503
final IndexMode indexMode,
475504
final String fullFieldName
476505
) {
477-
if (useDocValuesSkipper
478-
&& indexCreatedVersion.onOrAfter(IndexVersions.HOSTNAME_DOC_VALUES_SPARSE_INDEX)
479-
&& shouldUseDocValuesSkipper(hasDocValues.getValue(), indexSortConfig, indexMode, fullFieldName)) {
480-
return new FieldType(Defaults.FIELD_TYPE_WITH_SKIP_DOC_VALUES);
506+
if (enableDocValuesSkipper) {
507+
if (forceDocValuesSkipper) {
508+
assert hasDocValues.getValue();
509+
return new FieldType(Defaults.FIELD_TYPE_WITH_SKIP_DOC_VALUES);
510+
}
511+
if (indexCreatedVersion.onOrAfter(IndexVersions.HOSTNAME_DOC_VALUES_SPARSE_INDEX)
512+
&& shouldUseDocValuesSkipper(hasDocValues.getValue(), indexSortConfig, indexMode, fullFieldName)) {
513+
return new FieldType(Defaults.FIELD_TYPE_WITH_SKIP_DOC_VALUES);
514+
}
481515
}
482516
return new FieldType(Defaults.FIELD_TYPE);
483517
}
@@ -1088,7 +1122,8 @@ public String originalName() {
10881122
private final int ignoreAboveDefault;
10891123
private final IndexMode indexMode;
10901124
private final IndexSortConfig indexSortConfig;
1091-
private final boolean useDocValuesSkipper;
1125+
private final boolean enableDocValuesSkipper;
1126+
private final boolean forceDocValuesSkipper;
10921127
private final String offsetsFieldName;
10931128
private final SourceKeepMode indexSourceKeepMode;
10941129
private final String originalName;
@@ -1099,7 +1134,6 @@ private KeywordFieldMapper(
10991134
KeywordFieldType mappedFieldType,
11001135
BuilderParams builderParams,
11011136
boolean isSyntheticSource,
1102-
boolean useDocValuesSkipper,
11031137
Builder builder,
11041138
String offsetsFieldName,
11051139
SourceKeepMode indexSourceKeepMode
@@ -1120,7 +1154,8 @@ private KeywordFieldMapper(
11201154
this.ignoreAboveDefault = builder.ignoreAboveDefault;
11211155
this.indexMode = builder.indexMode;
11221156
this.indexSortConfig = builder.indexSortConfig;
1123-
this.useDocValuesSkipper = useDocValuesSkipper;
1157+
this.enableDocValuesSkipper = builder.enableDocValuesSkipper;
1158+
this.forceDocValuesSkipper = builder.forceDocValuesSkipper;
11241159
this.offsetsFieldName = offsetsFieldName;
11251160
this.indexSourceKeepMode = indexSourceKeepMode;
11261161
this.originalName = mappedFieldType.originalName();
@@ -1219,7 +1254,7 @@ private boolean indexValue(DocumentParserContext context, XContentString value)
12191254
throw new IllegalArgumentException(msg);
12201255
}
12211256

1222-
Field field = new KeywordField(fieldType().name(), binaryValue, fieldType);
1257+
Field field = buildKeywordField(binaryValue);
12231258
context.doc().add(field);
12241259

12251260
if (fieldType().hasDocValues() == false && fieldType.omitNorms()) {
@@ -1276,11 +1311,16 @@ public FieldMapper.Builder getMergeBuilder() {
12761311
indexCreatedVersion,
12771312
indexMode,
12781313
indexSortConfig,
1279-
useDocValuesSkipper,
1314+
enableDocValuesSkipper,
1315+
forceDocValuesSkipper,
12801316
indexSourceKeepMode
12811317
).dimension(fieldType().isDimension()).init(this);
12821318
}
12831319

1320+
public Field buildKeywordField(BytesRef binaryValue) {
1321+
return new KeywordField(fieldType().name(), binaryValue, fieldType);
1322+
}
1323+
12841324
@Override
12851325
public void doValidate(MappingLookup lookup) {
12861326
if (fieldType().isDimension() && null != lookup.nestedLookup().getNestedParent(fullPath())) {

x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/expression/predicate/regex/RegexMatch.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import org.elasticsearch.xpack.esql.core.type.DataType;
1616

1717
import java.util.Objects;
18+
import java.util.function.Predicate;
1819

1920
import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.ParamOrdinal.DEFAULT;
2021
import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.isStringAndExact;
@@ -67,6 +68,14 @@ public Boolean fold(FoldContext ctx) {
6768
throw new UnsupportedOperationException();
6869
}
6970

71+
/**
72+
* Returns an equivalent optimized expression taking into account the case of the pattern(s)
73+
* @param unwrappedField the field with to_upper/to_lower function removed
74+
* @param matchesCaseFn a predicate to check if a pattern matches the case
75+
* @return an optimized equivalent Expression or this if no optimization is possible
76+
*/
77+
public abstract Expression optimizeStringCasingWithInsensitiveRegexMatch(Expression unwrappedField, Predicate<String> matchesCaseFn);
78+
7079
@Override
7180
public boolean equals(Object obj) {
7281
if (super.equals(obj)) {

x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/operator/topn/TopNOperator.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,9 @@ public String describe() {
308308

309309
private Iterator<Page> output;
310310

311+
private long receiveNanos;
312+
private long emitNanos;
313+
311314
/**
312315
* Count of pages that have been received by this operator.
313316
*/
@@ -387,6 +390,7 @@ public boolean needsInput() {
387390

388391
@Override
389392
public void addInput(Page page) {
393+
long start = System.nanoTime();
390394
/*
391395
* Since row tracks memory we have to be careful to close any unused rows,
392396
* including any rows that fail while constructing because they allocate
@@ -422,13 +426,16 @@ public void addInput(Page page) {
422426
page.releaseBlocks();
423427
pagesReceived++;
424428
rowsReceived += page.getPositionCount();
429+
receiveNanos += System.nanoTime() - start;
425430
}
426431
}
427432

428433
@Override
429434
public void finish() {
430435
if (output == null) {
436+
long start = System.nanoTime();
431437
output = toPages();
438+
emitNanos += System.nanoTime() - start;
432439
}
433440
}
434441

@@ -588,7 +595,16 @@ public long ramBytesUsed() {
588595

589596
@Override
590597
public Status status() {
591-
return new TopNOperatorStatus(inputQueue.size(), ramBytesUsed(), pagesReceived, pagesEmitted, rowsReceived, rowsEmitted);
598+
return new TopNOperatorStatus(
599+
receiveNanos,
600+
emitNanos,
601+
inputQueue.size(),
602+
ramBytesUsed(),
603+
pagesReceived,
604+
pagesEmitted,
605+
rowsReceived,
606+
rowsEmitted
607+
);
592608
}
593609

594610
@Override

0 commit comments

Comments
 (0)