Skip to content

Commit 2bb1d34

Browse files
authored
Merge pull request #246 from weaviate/#219/add-hybrid-to-aggregate
Make improvments to hybrid ux
2 parents a254718 + fea9b0d commit 2bb1d34

File tree

5 files changed

+278
-51
lines changed

5 files changed

+278
-51
lines changed

.github/workflows/main.yaml

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ env:
1010
WEAVIATE_124: 1.24.26
1111
WEAVIATE_125: 1.25.28
1212
WEAVIATE_126: 1.26.13
13-
WEAVIATE_127: 1.27.8
14-
WEAVIATE_128: 1.28.1-77a2178
13+
WEAVIATE_127: 1.27.9
14+
WEAVIATE_128: 1.28.2
1515

1616
jobs:
1717
checks:

src/collections/aggregate/index.ts

+118-47
Original file line numberDiff line numberDiff line change
@@ -7,36 +7,50 @@ import { FilterValue } from '../filters/index.js';
77

88
import { WeaviateQueryError } from '../../errors.js';
99
import { Aggregator } from '../../graphql/index.js';
10-
import { toBase64FromMedia } from '../../index.js';
10+
import { PrimitiveKeys, toBase64FromMedia } from '../../index.js';
11+
import { Bm25QueryProperty } from '../query/types.js';
1112
import { Serialize } from '../serialize/index.js';
1213

13-
export type AggregateBaseOptions<T, M> = {
14+
export type AggregateBaseOptions<M> = {
1415
filters?: FilterValue;
1516
returnMetrics?: M;
1617
};
1718

18-
export type AggregateGroupByOptions<T, M> = AggregateOptions<T, M> & {
19-
groupBy: (keyof T & string) | GroupByAggregate<T>;
19+
export type PropertyOf<T> = T extends undefined ? string : keyof T & string;
20+
21+
export type AggregateGroupByOptions<T, M> = AggregateBaseOptions<M> & {
22+
groupBy: PropertyOf<T> | GroupByAggregate<T>;
2023
};
2124

2225
export type GroupByAggregate<T> = {
23-
property: keyof T & string;
26+
property: PropertyOf<T>;
2427
limit?: number;
2528
};
2629

27-
export type AggregateOptions<T, M> = AggregateBaseOptions<T, M>;
28-
29-
export type AggregateBaseOverAllOptions<T, M> = AggregateBaseOptions<T, M>;
30+
export type AggregateOverAllOptions<M> = AggregateBaseOptions<M>;
3031

31-
export type AggregateNearOptions<T, M> = AggregateBaseOptions<T, M> & {
32+
export type AggregateNearOptions<M> = AggregateBaseOptions<M> & {
3233
certainty?: number;
3334
distance?: number;
3435
objectLimit?: number;
3536
targetVector?: string;
3637
};
3738

38-
export type AggregateGroupByNearOptions<T, M> = AggregateNearOptions<T, M> & {
39-
groupBy: (keyof T & string) | GroupByAggregate<T>;
39+
export type AggregateHybridOptions<T, M> = AggregateBaseOptions<M> & {
40+
alpha?: number;
41+
maxVectorDistance?: number;
42+
objectLimit?: number;
43+
queryProperties?: (PrimitiveKeys<T> | Bm25QueryProperty<T>)[];
44+
targetVector?: string;
45+
vector?: number[];
46+
};
47+
48+
export type AggregateGroupByHybridOptions<T, M> = AggregateHybridOptions<T, M> & {
49+
groupBy: PropertyOf<T> | GroupByAggregate<T>;
50+
};
51+
52+
export type AggregateGroupByNearOptions<T, M> = AggregateNearOptions<M> & {
53+
groupBy: PropertyOf<T> | GroupByAggregate<T>;
4054
};
4155

4256
export type AggregateBoolean = {
@@ -126,11 +140,11 @@ export type AggregateMetrics<M> = {
126140
[K in keyof M]: M[K] extends true ? number : never;
127141
};
128142

129-
export type MetricsProperty<T> = T extends undefined ? string : keyof T & string;
143+
export type MetricsProperty<T> = PropertyOf<T>;
130144

131145
export const metrics = <T>() => {
132146
return {
133-
aggregate: <P extends MetricsProperty<T>>(property: P) => new MetricsManager<T, P>(property),
147+
aggregate: <P extends PropertyOf<T>>(property: P) => new MetricsManager<T, P>(property),
134148
};
135149
};
136150

@@ -143,10 +157,10 @@ export interface Metrics<T> {
143157
144158
See [the docs](https://weaviate.io/developers/weaviate/search/aggregate) for more details!
145159
*/
146-
aggregate: <P extends MetricsProperty<T>>(property: P) => MetricsManager<T, P>;
160+
aggregate: <P extends PropertyOf<T>>(property: P) => MetricsManager<T, P>;
147161
}
148162

149-
export class MetricsManager<T, P extends MetricsProperty<T>> {
163+
export class MetricsManager<T, P extends PropertyOf<T>> {
150164
private propertyName: P;
151165

152166
constructor(property: P) {
@@ -346,9 +360,26 @@ class AggregateManager<T> implements Aggregate<T> {
346360
this.tenant = tenant;
347361

348362
this.groupBy = {
363+
hybrid: <M extends PropertiesMetrics<T> | undefined = undefined>(
364+
query: string,
365+
opts: AggregateGroupByHybridOptions<T, M>
366+
): Promise<AggregateGroupByResult<T, M>[]> => {
367+
let builder = this.base(opts?.returnMetrics, opts?.filters, opts?.groupBy).withHybrid({
368+
query: query,
369+
alpha: opts?.alpha,
370+
maxVectorDistance: opts?.maxVectorDistance,
371+
properties: opts?.queryProperties as string[],
372+
targetVectors: opts?.targetVector ? [opts.targetVector] : undefined,
373+
vector: opts?.vector,
374+
});
375+
if (opts?.objectLimit) {
376+
builder = builder.withObjectLimit(opts.objectLimit);
377+
}
378+
return this.doGroupBy(builder);
379+
},
349380
nearImage: async <M extends PropertiesMetrics<T> | undefined = undefined>(
350381
image: string | Buffer,
351-
opts?: AggregateGroupByNearOptions<T, M>
382+
opts: AggregateGroupByNearOptions<T, M>
352383
): Promise<AggregateGroupByResult<T, M>[]> => {
353384
const builder = this.base(opts?.returnMetrics, opts?.filters, opts?.groupBy).withNearImage({
354385
image: await toBase64FromMedia(image),
@@ -363,7 +394,7 @@ class AggregateManager<T> implements Aggregate<T> {
363394
},
364395
nearObject: <M extends PropertiesMetrics<T> | undefined = undefined>(
365396
id: string,
366-
opts?: AggregateGroupByNearOptions<T, M>
397+
opts: AggregateGroupByNearOptions<T, M>
367398
): Promise<AggregateGroupByResult<T, M>[]> => {
368399
const builder = this.base(opts?.returnMetrics, opts?.filters, opts?.groupBy).withNearObject({
369400
id: id,
@@ -378,7 +409,7 @@ class AggregateManager<T> implements Aggregate<T> {
378409
},
379410
nearText: <M extends PropertiesMetrics<T> | undefined = undefined>(
380411
query: string | string[],
381-
opts?: AggregateGroupByNearOptions<T, M>
412+
opts: AggregateGroupByNearOptions<T, M>
382413
): Promise<AggregateGroupByResult<T, M>[]> => {
383414
const builder = this.base(opts?.returnMetrics, opts?.filters, opts?.groupBy).withNearText({
384415
concepts: Array.isArray(query) ? query : [query],
@@ -393,7 +424,7 @@ class AggregateManager<T> implements Aggregate<T> {
393424
},
394425
nearVector: <M extends PropertiesMetrics<T> | undefined = undefined>(
395426
vector: number[],
396-
opts?: AggregateGroupByNearOptions<T, M>
427+
opts: AggregateGroupByNearOptions<T, M>
397428
): Promise<AggregateGroupByResult<T, M>[]> => {
398429
const builder = this.base(opts?.returnMetrics, opts?.filters, opts?.groupBy).withNearVector({
399430
vector: vector,
@@ -419,11 +450,7 @@ class AggregateManager<T> implements Aggregate<T> {
419450
return new Aggregator(this.connection);
420451
}
421452

422-
base(
423-
metrics?: PropertiesMetrics<T>,
424-
filters?: FilterValue,
425-
groupBy?: (keyof T & string) | GroupByAggregate<T>
426-
) {
453+
base(metrics?: PropertiesMetrics<T>, filters?: FilterValue, groupBy?: PropertyOf<T> | GroupByAggregate<T>) {
427454
let fields = 'meta { count }';
428455
let builder = this.query().withClassName(this.name);
429456
if (metrics) {
@@ -489,9 +516,27 @@ class AggregateManager<T> implements Aggregate<T> {
489516
return new AggregateManager<T>(connection, name, dbVersionSupport, consistencyLevel, tenant);
490517
}
491518

519+
hybrid<M extends PropertiesMetrics<T>>(
520+
query: string,
521+
opts?: AggregateHybridOptions<T, M>
522+
): Promise<AggregateResult<T, M>> {
523+
let builder = this.base(opts?.returnMetrics, opts?.filters).withHybrid({
524+
query: query,
525+
alpha: opts?.alpha,
526+
maxVectorDistance: opts?.maxVectorDistance,
527+
properties: opts?.queryProperties as string[],
528+
targetVectors: opts?.targetVector ? [opts.targetVector] : undefined,
529+
vector: opts?.vector,
530+
});
531+
if (opts?.objectLimit) {
532+
builder = builder.withObjectLimit(opts.objectLimit);
533+
}
534+
return this.do(builder);
535+
}
536+
492537
async nearImage<M extends PropertiesMetrics<T>>(
493538
image: string | Buffer,
494-
opts?: AggregateNearOptions<T, M>
539+
opts?: AggregateNearOptions<M>
495540
): Promise<AggregateResult<T, M>> {
496541
const builder = this.base(opts?.returnMetrics, opts?.filters).withNearImage({
497542
image: await toBase64FromMedia(image),
@@ -507,7 +552,7 @@ class AggregateManager<T> implements Aggregate<T> {
507552

508553
nearObject<M extends PropertiesMetrics<T>>(
509554
id: string,
510-
opts?: AggregateNearOptions<T, M>
555+
opts?: AggregateNearOptions<M>
511556
): Promise<AggregateResult<T, M>> {
512557
const builder = this.base(opts?.returnMetrics, opts?.filters).withNearObject({
513558
id: id,
@@ -523,7 +568,7 @@ class AggregateManager<T> implements Aggregate<T> {
523568

524569
nearText<M extends PropertiesMetrics<T>>(
525570
query: string | string[],
526-
opts?: AggregateNearOptions<T, M>
571+
opts?: AggregateNearOptions<M>
527572
): Promise<AggregateResult<T, M>> {
528573
const builder = this.base(opts?.returnMetrics, opts?.filters).withNearText({
529574
concepts: Array.isArray(query) ? query : [query],
@@ -539,7 +584,7 @@ class AggregateManager<T> implements Aggregate<T> {
539584

540585
nearVector<M extends PropertiesMetrics<T>>(
541586
vector: number[],
542-
opts?: AggregateNearOptions<T, M>
587+
opts?: AggregateNearOptions<M>
543588
): Promise<AggregateResult<T, M>> {
544589
const builder = this.base(opts?.returnMetrics, opts?.filters).withNearVector({
545590
vector: vector,
@@ -553,7 +598,7 @@ class AggregateManager<T> implements Aggregate<T> {
553598
return this.do(builder);
554599
}
555600

556-
overAll<M extends PropertiesMetrics<T>>(opts?: AggregateOptions<T, M>): Promise<AggregateResult<T, M>> {
601+
overAll<M extends PropertiesMetrics<T>>(opts?: AggregateOverAllOptions<M>): Promise<AggregateResult<T, M>> {
557602
const builder = this.base(opts?.returnMetrics, opts?.filters);
558603
return this.do(builder);
559604
}
@@ -588,7 +633,7 @@ class AggregateManager<T> implements Aggregate<T> {
588633
prop: groupedBy.path[0],
589634
value: groupedBy.value,
590635
},
591-
properties: rest.length > 0 ? rest : undefined,
636+
properties: rest,
592637
totalCount: meta?.count,
593638
};
594639
})
@@ -602,6 +647,19 @@ class AggregateManager<T> implements Aggregate<T> {
602647
export interface Aggregate<T> {
603648
/** This namespace contains methods perform a group by search while aggregating metrics. */
604649
groupBy: AggregateGroupBy<T>;
650+
/**
651+
* Aggregate metrics over the objects returned by a hybrid search on this collection.
652+
*
653+
* This method requires that the objects in the collection have associated vectors.
654+
*
655+
* @param {string} query The text query to search for.
656+
* @param {AggregateHybridOptions<T, M>} opts The options for the request.
657+
* @returns {Promise<AggregateResult<T, M>[]>} The aggregated metrics for the objects returned by the vector search.
658+
*/
659+
hybrid<M extends PropertiesMetrics<T>>(
660+
query: string,
661+
opts?: AggregateHybridOptions<T, M>
662+
): Promise<AggregateResult<T, M>>;
605663
/**
606664
* Aggregate metrics over the objects returned by a near image vector search on this collection.
607665
*
@@ -615,7 +673,7 @@ export interface Aggregate<T> {
615673
*/
616674
nearImage<M extends PropertiesMetrics<T>>(
617675
image: string | Buffer,
618-
opts?: AggregateNearOptions<T, M>
676+
opts?: AggregateNearOptions<M>
619677
): Promise<AggregateResult<T, M>>;
620678
/**
621679
* Aggregate metrics over the objects returned by a near object search on this collection.
@@ -630,7 +688,7 @@ export interface Aggregate<T> {
630688
*/
631689
nearObject<M extends PropertiesMetrics<T>>(
632690
id: string,
633-
opts?: AggregateNearOptions<T, M>
691+
opts?: AggregateNearOptions<M>
634692
): Promise<AggregateResult<T, M>>;
635693
/**
636694
* Aggregate metrics over the objects returned by a near vector search on this collection.
@@ -645,7 +703,7 @@ export interface Aggregate<T> {
645703
*/
646704
nearText<M extends PropertiesMetrics<T>>(
647705
query: string | string[],
648-
opts?: AggregateNearOptions<T, M>
706+
opts?: AggregateNearOptions<M>
649707
): Promise<AggregateResult<T, M>>;
650708
/**
651709
* Aggregate metrics over the objects returned by a near vector search on this collection.
@@ -660,80 +718,93 @@ export interface Aggregate<T> {
660718
*/
661719
nearVector<M extends PropertiesMetrics<T>>(
662720
vector: number[],
663-
opts?: AggregateNearOptions<T, M>
721+
opts?: AggregateNearOptions<M>
664722
): Promise<AggregateResult<T, M>>;
665723
/**
666724
* Aggregate metrics over all the objects in this collection without any vector search.
667725
*
668726
* @param {AggregateOptions<T, M>} [opts] The options for the request.
669727
* @returns {Promise<AggregateResult<T, M>[]>} The aggregated metrics for the objects in the collection.
670728
*/
671-
overAll<M extends PropertiesMetrics<T>>(opts?: AggregateOptions<T, M>): Promise<AggregateResult<T, M>>;
729+
overAll<M extends PropertiesMetrics<T>>(opts?: AggregateOverAllOptions<M>): Promise<AggregateResult<T, M>>;
672730
}
673731

674732
export interface AggregateGroupBy<T> {
675733
/**
676-
* Aggregate metrics over the objects returned by a near image vector search on this collection.
734+
* Aggregate metrics over the objects grouped by a specified property and returned by a hybrid search on this collection.
735+
*
736+
* This method requires that the objects in the collection have associated vectors.
737+
*
738+
* @param {string} query The text query to search for.
739+
* @param {AggregateGroupByHybridOptions<T, M>} opts The options for the request.
740+
* @returns {Promise<AggregateGroupByResult<T, M>[]>} The aggregated metrics for the objects returned by the vector search.
741+
*/
742+
hybrid<M extends PropertiesMetrics<T>>(
743+
query: string,
744+
opts: AggregateGroupByHybridOptions<T, M>
745+
): Promise<AggregateGroupByResult<T, M>[]>;
746+
/**
747+
* Aggregate metrics over the objects grouped by a specified property and returned by a near image vector search on this collection.
677748
*
678749
* At least one of `certainty`, `distance`, or `object_limit` must be specified here for the vector search.
679750
*
680751
* This method requires a vectorizer capable of handling base64-encoded images, e.g. `img2vec-neural`, `multi2vec-clip`, and `multi2vec-bind`.
681752
*
682753
* @param {string | Buffer} image The image to search on. This can be a base64 string, a file path string, or a buffer.
683-
* @param {AggregateGroupByNearOptions<T, M>} [opts] The options for the request.
754+
* @param {AggregateGroupByNearOptions<T, M>} opts The options for the request.
684755
* @returns {Promise<AggregateGroupByResult<T, M>[]>} The aggregated metrics for the objects returned by the vector search.
685756
*/
686757
nearImage<M extends PropertiesMetrics<T>>(
687758
image: string | Buffer,
688-
opts?: AggregateGroupByNearOptions<T, M>
759+
opts: AggregateGroupByNearOptions<T, M>
689760
): Promise<AggregateGroupByResult<T, M>[]>;
690761
/**
691-
* Aggregate metrics over the objects returned by a near object search on this collection.
762+
* Aggregate metrics over the objects grouped by a specified property and returned by a near object search on this collection.
692763
*
693764
* At least one of `certainty`, `distance`, or `object_limit` must be specified here for the vector search.
694765
*
695766
* This method requires that the objects in the collection have associated vectors.
696767
*
697768
* @param {string} id The ID of the object to search for.
698-
* @param {AggregateGroupByNearOptions<T, M>} [opts] The options for the request.
769+
* @param {AggregateGroupByNearOptions<T, M>} opts The options for the request.
699770
* @returns {Promise<AggregateGroupByResult<T, M>[]>} The aggregated metrics for the objects returned by the vector search.
700771
*/
701772
nearObject<M extends PropertiesMetrics<T>>(
702773
id: string,
703-
opts?: AggregateGroupByNearOptions<T, M>
774+
opts: AggregateGroupByNearOptions<T, M>
704775
): Promise<AggregateGroupByResult<T, M>[]>;
705776
/**
706-
* Aggregate metrics over the objects returned by a near text vector search on this collection.
777+
* Aggregate metrics over the objects grouped by a specified property and returned by a near text vector search on this collection.
707778
*
708779
* At least one of `certainty`, `distance`, or `object_limit` must be specified here for the vector search.
709780
*
710781
* This method requires a vectorizer capable of handling text, e.g. `text2vec-contextionary`, `text2vec-openai`, etc.
711782
*
712783
* @param {string | string[]} query The text to search for.
713-
* @param {AggregateGroupByNearOptions<T, M>} [opts] The options for the request.
784+
* @param {AggregateGroupByNearOptions<T, M>} opts The options for the request.
714785
* @returns {Promise<AggregateGroupByResult<T, M>[]>} The aggregated metrics for the objects returned by the vector search.
715786
*/
716787
nearText<M extends PropertiesMetrics<T>>(
717788
query: string | string[],
718789
opts: AggregateGroupByNearOptions<T, M>
719790
): Promise<AggregateGroupByResult<T, M>[]>;
720791
/**
721-
* Aggregate metrics over the objects returned by a near vector search on this collection.
792+
* Aggregate metrics over the objects grouped by a specified property and returned by a near vector search on this collection.
722793
*
723794
* At least one of `certainty`, `distance`, or `object_limit` must be specified here for the vector search.
724795
*
725796
* This method requires that the objects in the collection have associated vectors.
726797
*
727798
* @param {number[]} vector The vector to search for.
728-
* @param {AggregateGroupByNearOptions<T, M>} [opts] The options for the request.
799+
* @param {AggregateGroupByNearOptions<T, M>} opts The options for the request.
729800
* @returns {Promise<AggregateGroupByResult<T, M>[]>} The aggregated metrics for the objects returned by the vector search.
730801
*/
731802
nearVector<M extends PropertiesMetrics<T>>(
732803
vector: number[],
733-
opts?: AggregateGroupByNearOptions<T, M>
804+
opts: AggregateGroupByNearOptions<T, M>
734805
): Promise<AggregateGroupByResult<T, M>[]>;
735806
/**
736-
* Aggregate metrics over all the objects in this collection without any vector search.
807+
* Aggregate metrics over all the objects in this collection grouped by a specified property without any vector search.
737808
*
738809
* @param {AggregateGroupByOptions<T, M>} [opts] The options for the request.
739810
* @returns {Promise<AggregateGroupByResult<T, M>[]>} The aggregated metrics for the objects in the collection.

0 commit comments

Comments
 (0)