Skip to content

Commit 19331a7

Browse files
committed
Enhance client and generative capabilities:
- Refactor connection setup to include OpenAI API key support - Update generative models to use IList for better dx - Add new tests for generative results and group by functionality - Improve handling of generative responses in gRPC client
1 parent e65b89c commit 19331a7

File tree

10 files changed

+400
-193
lines changed

10 files changed

+400
-193
lines changed

src/Weaviate.Client.Tests/Integration/TestCollections.cs

Lines changed: 0 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -5,134 +5,6 @@ namespace Weaviate.Client.Tests.Integration;
55
[Collection("TestCollections")]
66
public partial class CollectionsTests : IntegrationTests
77
{
8-
[Fact]
9-
public async Task Test_Collection_Generative_FetchObjects()
10-
{
11-
// Arrange: create collection with no vectorizer
12-
var collection = await CollectionFactory(
13-
properties: [Property.Text("text")],
14-
vectorConfig: Configure.Vectors.SelfProvided(),
15-
generativeConfig: new GenerativeConfig.Custom
16-
{
17-
Type = "generative-dummy",
18-
Config = new { ConfigOption = "ConfigValue" },
19-
}
20-
);
21-
22-
// Insert data
23-
await collection.Data.InsertMany(
24-
BatchInsertRequest.Create<object>(
25-
new[] { new { text = "John Doe" }, new { text = "Jane Doe" } }
26-
)
27-
);
28-
29-
// Act: generative fetch
30-
var res = await collection.Generate.FetchObjects(
31-
prompt: new SinglePrompt { Prompt = "Who is this? {text}" },
32-
groupedPrompt: new GroupedPrompt
33-
{
34-
Task = "Who are these people?",
35-
Properties = new List<string> { "text" },
36-
}
37-
);
38-
39-
// Assert
40-
Assert.NotNull(res);
41-
Assert.NotNull(res.Generative);
42-
Assert.NotNull(res.Objects);
43-
Assert.Equal(2, res.Objects.Count());
44-
45-
foreach (var obj in res.Objects)
46-
{
47-
Assert.NotNull(obj.Generative);
48-
Assert.Contains(
49-
"I'm sorry, I'm just a dummy and can't generate anything.",
50-
obj.Generative.Values[0].Result
51-
);
52-
53-
// The value of the Result property can be
54-
// accessed by index of Generative,
55-
// or via Generative.Values[] indexer.
56-
// They return the same value.
57-
// The entries in the Values list contain additional properties.
58-
Assert.Same(obj.Generative.Values[0].Result, obj.Generative[0]);
59-
}
60-
}
61-
62-
public static IEnumerable<object?[]> GenerateByIdsTestData()
63-
{
64-
var uuid1 = _reusableUuids[0];
65-
var uuid2 = _reusableUuids[1];
66-
var uuid3 = _reusableUuids[2];
67-
68-
yield return new object?[] { Array.Empty<Guid>(), 0, new HashSet<Guid>() };
69-
yield return new object?[] { new Guid[] { }, 0, new HashSet<Guid>() };
70-
yield return new object?[]
71-
{
72-
new Guid[] { uuid3 },
73-
1,
74-
new HashSet<Guid> { uuid3 },
75-
};
76-
yield return new object?[]
77-
{
78-
new Guid[] { uuid1, uuid2 },
79-
2,
80-
new HashSet<Guid> { uuid1, uuid2 },
81-
};
82-
yield return new object?[]
83-
{
84-
new Guid[] { uuid1, uuid3 },
85-
2,
86-
new HashSet<Guid> { uuid1, uuid3 },
87-
};
88-
yield return new object?[]
89-
{
90-
new Guid[] { uuid1, uuid3, uuid3 },
91-
2,
92-
new HashSet<Guid> { uuid1, uuid3 },
93-
};
94-
}
95-
96-
[Theory]
97-
[MemberData(nameof(GenerateByIdsTestData))]
98-
public async Task Test_Generate_By_Ids(Guid[] ids, int expectedLen, HashSet<Guid> expected)
99-
{
100-
var collection = await CollectionFactory(
101-
vectorConfig: Configure.Vectors.SelfProvided(),
102-
properties: [Property.Text("text")],
103-
generativeConfig: new GenerativeConfig.Custom
104-
{
105-
Type = "generative-dummy",
106-
Config = new { ConfigOption = "ConfigValue" },
107-
}
108-
);
109-
110-
var result = await collection.Data.InsertMany(
111-
(new { text = "John Doe" }, id: _reusableUuids[0]),
112-
(new { text = "Jane Doe" }, id: _reusableUuids[1]),
113-
(new { text = "J. Doe" }, id: _reusableUuids[2])
114-
);
115-
116-
var res = await collection.Generate.FetchObjectsByIDs(
117-
[.. ids],
118-
prompt: new SinglePrompt { Prompt = "Who is this? {text}" },
119-
groupedPrompt: new GroupedPrompt
120-
{
121-
Task = "Who are these people?",
122-
Properties = new List<string> { "text" },
123-
}
124-
);
125-
126-
Assert.NotNull(res);
127-
Assert.NotNull(res.Generative);
128-
Assert.Equal(expectedLen, res.Objects.Count());
129-
Assert.Equal(expected, res.Objects.Select(o => o.ID!.Value).ToHashSet());
130-
foreach (var obj in res.Objects)
131-
{
132-
Assert.NotNull(obj.Generative);
133-
}
134-
}
135-
1368
[Fact]
1379
public async Task CollectionClient_Creates_And_Retrieves_Collection()
13810
{

src/Weaviate.Client.Tests/Integration/TestQueries.cs

Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,4 +61,202 @@ public async Task Test_Sorting(string propertyName)
6161
Assert.Equal(new List<string> { "Charlie", "Bob", "Alice" }, namesDesc);
6262
Assert.Equal(new List<string> { "Alice", "Bob", "Charlie" }, namesAsc);
6363
}
64+
65+
[Fact]
66+
public async Task Test_BM25_Generate_And_GroupBy_With_Everything()
67+
{
68+
// Arrange
69+
var collection = await this.CollectionFactory<object>(
70+
properties: [Property.Text("text"), Property.Text("content")],
71+
vectorConfig: new VectorConfig("default", new Vectorizer.SelfProvided()),
72+
generativeConfig: new GenerativeConfig.Custom
73+
{
74+
Type = "generative-dummy",
75+
Config = new { ConfigOption = "ConfigValue" },
76+
}
77+
);
78+
79+
var testData = new[]
80+
{
81+
new
82+
{
83+
text = "apples are big",
84+
content = "Teddy is the biggest and bigger than everything else",
85+
},
86+
new
87+
{
88+
text = "bananas are small",
89+
content = "cats are the smallest and smaller than everything else",
90+
},
91+
};
92+
93+
await collection.Data.InsertMany(BatchInsertRequest.Create<object>(testData));
94+
95+
// Act
96+
var groupBy = new GroupByRequest
97+
{
98+
PropertyName = "text",
99+
NumberOfGroups = 2,
100+
ObjectsPerGroup = 1,
101+
};
102+
103+
var res = await collection.Generate.BM25(
104+
query: "Teddy",
105+
groupBy: groupBy,
106+
searchFields: new[] { "content" },
107+
prompt: new SinglePrompt
108+
{
109+
Prompt =
110+
"Is there something to eat in {text}? Only answer yes if there is something to eat or no if not without punctuation",
111+
},
112+
groupedPrompt: new GroupedPrompt
113+
{
114+
Task =
115+
"What is the biggest and what is the smallest? Only write the names separated by a space",
116+
}
117+
);
118+
119+
// Assert
120+
Assert.NotNull(res);
121+
Assert.NotNull(res.Generative);
122+
Assert.NotEmpty(res.Generative);
123+
Assert.Contains("prompt: What is the biggest", res.Generative[0]);
124+
Assert.Single(res.Groups);
125+
var groups = res.Groups.Values.ToList();
126+
// Get the first object in the first group and check its generative result
127+
var firstGroupObject = groups[0];
128+
Assert.NotNull(firstGroupObject);
129+
Assert.NotNull(firstGroupObject.Generative);
130+
Assert.Contains(
131+
"Is there something to eat in apples are big",
132+
firstGroupObject.Generative[0]
133+
);
134+
// Get the first object in the result set and check its group
135+
var firstObject = res.Objects[0];
136+
Assert.Equal("apples are big", firstObject.BelongsToGroup);
137+
}
138+
139+
[Fact]
140+
public async Task Test_Collection_Generative_FetchObjects()
141+
{
142+
// Arrange: create collection with no vectorizer
143+
var collection = await CollectionFactory(
144+
properties: [Property.Text("text")],
145+
vectorConfig: Configure.Vectors.SelfProvided(),
146+
generativeConfig: new GenerativeConfig.Custom
147+
{
148+
Type = "generative-dummy",
149+
Config = new { ConfigOption = "ConfigValue" },
150+
}
151+
);
152+
153+
// Insert data
154+
await collection.Data.InsertMany(
155+
BatchInsertRequest.Create<object>(
156+
new[] { new { text = "John Doe" }, new { text = "Jane Doe" } }
157+
)
158+
);
159+
160+
// Act: generative fetch
161+
var res = await collection.Generate.FetchObjects(
162+
prompt: new SinglePrompt { Prompt = "Who is this? {text}" },
163+
groupedPrompt: new GroupedPrompt { Task = "Who are these people?", Properties = "text" }
164+
);
165+
166+
// Assert
167+
Assert.NotNull(res);
168+
Assert.NotNull(res.Generative);
169+
Assert.NotNull(res.Objects);
170+
Assert.Equal(2, res.Objects.Count());
171+
172+
foreach (var obj in res.Objects)
173+
{
174+
Assert.NotNull(obj.Generative);
175+
Assert.Contains(
176+
"I'm sorry, I'm just a dummy and can't generate anything.",
177+
obj.Generative.Values[0].Result
178+
);
179+
180+
// The value of the Result property can be
181+
// accessed by index of Generative,
182+
// or via Generative.Values[] indexer.
183+
// They return the same value.
184+
// The entries in the Values list contain additional properties.
185+
Assert.Same(obj.Generative.Values[0].Result, obj.Generative[0]);
186+
}
187+
}
188+
189+
public static IEnumerable<object?[]> GenerateByIdsTestData()
190+
{
191+
var uuid1 = _reusableUuids[0];
192+
var uuid2 = _reusableUuids[1];
193+
var uuid3 = _reusableUuids[2];
194+
195+
yield return new object?[] { Array.Empty<Guid>(), 0, new HashSet<Guid>() };
196+
yield return new object?[] { new Guid[] { }, 0, new HashSet<Guid>() };
197+
yield return new object?[]
198+
{
199+
new Guid[] { uuid3 },
200+
1,
201+
new HashSet<Guid> { uuid3 },
202+
};
203+
yield return new object?[]
204+
{
205+
new Guid[] { uuid1, uuid2 },
206+
2,
207+
new HashSet<Guid> { uuid1, uuid2 },
208+
};
209+
yield return new object?[]
210+
{
211+
new Guid[] { uuid1, uuid3 },
212+
2,
213+
new HashSet<Guid> { uuid1, uuid3 },
214+
};
215+
yield return new object?[]
216+
{
217+
new Guid[] { uuid1, uuid3, uuid3 },
218+
2,
219+
new HashSet<Guid> { uuid1, uuid3 },
220+
};
221+
}
222+
223+
[Theory]
224+
[MemberData(nameof(GenerateByIdsTestData))]
225+
public async Task Test_Generate_By_Ids(Guid[] ids, int expectedLen, HashSet<Guid> expected)
226+
{
227+
var collection = await CollectionFactory(
228+
vectorConfig: Configure.Vectors.SelfProvided(),
229+
properties: [Property.Text("text")],
230+
generativeConfig: new GenerativeConfig.Custom
231+
{
232+
Type = "generative-dummy",
233+
Config = new { ConfigOption = "ConfigValue" },
234+
}
235+
);
236+
237+
var result = await collection.Data.InsertMany(
238+
(new { text = "John Doe" }, id: _reusableUuids[0]),
239+
(new { text = "Jane Doe" }, id: _reusableUuids[1]),
240+
(new { text = "J. Doe" }, id: _reusableUuids[2])
241+
);
242+
243+
var res = await collection.Generate.FetchObjectsByIDs(
244+
[.. ids],
245+
prompt: new SinglePrompt { Prompt = "Who is this? {text}" },
246+
groupedPrompt: new GroupedPrompt
247+
{
248+
Task = "Who are these people?",
249+
Properties = new List<string> { "text" },
250+
}
251+
);
252+
253+
Assert.NotNull(res);
254+
Assert.NotNull(res.Generative);
255+
Assert.Equal(expectedLen, res.Objects.Count());
256+
Assert.Equal(expected, res.Objects.Select(o => o.ID!.Value).ToHashSet());
257+
foreach (var obj in res.Objects)
258+
{
259+
Assert.NotNull(obj.Generative);
260+
}
261+
}
64262
}

src/Weaviate.Client.Tests/Integration/_Integration.cs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,17 @@ public IntegrationTests()
3939
InnerHandler = new HttpClientHandler(),
4040
};
4141

42-
_weaviate = Connect.Local(httpMessageHandler: _httpMessageHandler);
42+
var builder = WeaviateClientBuilder.Local(httpMessageHandler: _httpMessageHandler);
43+
44+
if (
45+
Environment.GetEnvironmentVariable("WEAVIATE_OPENAI_API_KEY") is { } openaiKey
46+
&& !string.IsNullOrEmpty(openaiKey)
47+
)
48+
{
49+
builder.WithOpenAI(openaiKey);
50+
}
51+
52+
_weaviate = builder.Build();
4353
}
4454

4555
public async ValueTask DisposeAsync()

0 commit comments

Comments
 (0)