WEBVTT

1
00:00:00.620 --> 00:00:04.960
Now that we have our understanding of vectors

2
00:00:04.960 --> 00:00:06.700
and what we are going to put into

3
00:00:06.700 --> 00:00:09.020
a vector store, let's build the vector store

4
00:00:09.020 --> 00:00:10.660
and ingest some data.

5
00:00:11.700 --> 00:00:14.260
And in order to do that, I've made

6
00:00:14.260 --> 00:00:18.220
up a few dummy samples of some kind

7
00:00:18.220 --> 00:00:20.920
of internal handbook or knowledge base at a

8
00:00:20.920 --> 00:00:21.280
company.

9
00:00:22.020 --> 00:00:25.500
And one of the questions is our previous

10
00:00:25.500 --> 00:00:27.720
question about what is the office password.

11
00:00:28.140 --> 00:00:31.100
But there's other things like is Christmas Eve

12
00:00:31.100 --> 00:00:34.760
a holiday, how to register for vacation and

13
00:00:34.760 --> 00:00:35.260
such a thing.

14
00:00:35.280 --> 00:00:36.660
Doesn't really matter.

15
00:00:37.400 --> 00:00:38.820
And this is just 10.

16
00:00:39.080 --> 00:00:41.560
That would be several hundred in a normal

17
00:00:41.560 --> 00:00:43.640
company probably.

18
00:00:44.820 --> 00:00:49.120
But we have this data, and we're going

19
00:00:49.120 --> 00:00:51.720
to make a normal connection as before.

20
00:00:52.300 --> 00:00:55.040
And we're going to make the vector generator.

21
00:00:56.100 --> 00:00:58.580
And then we're going to choose our vector

22
00:00:58.580 --> 00:01:00.080
store.

23
00:01:00.940 --> 00:01:04.780
So there's various options, but I have chosen

24
00:01:04.780 --> 00:01:08.620
in this case a SQLite because it is

25
00:01:08.620 --> 00:01:12.100
easy to work with, although a bit limited.

26
00:01:12.640 --> 00:01:17.660
There is certain that have just taken on

27
00:01:17.660 --> 00:01:19.500
the job and say, hey, I also want

28
00:01:19.500 --> 00:01:20.440
to be a vector store.

29
00:01:20.660 --> 00:01:22.940
SQLite was officially just a SQL.

30
00:01:23.820 --> 00:01:28.140
While others have been dedicated from day one

31
00:01:28.140 --> 00:01:29.220
to being a vector store.

32
00:01:30.540 --> 00:01:32.740
So there's different options.

33
00:01:33.200 --> 00:01:36.540
And up here, we can see Azure AI

34
00:01:36.540 --> 00:01:40.800
Search, Cosmos DB, Elasticsearch in

35
00:01:40.800 --> 00:01:43.680
memory, and all kinds of different vector stores.

36
00:01:44.400 --> 00:01:46.900
I will show a few examples down here

37
00:01:46.900 --> 00:01:48.740
of the ones I have tried.

38
00:01:49.510 --> 00:01:54.920
But we need a new NuGet package in

39
00:01:54.920 --> 00:01:55.800
order to do this.

40
00:01:56.820 --> 00:01:58.920
So I have put in one more NuGet

41
00:01:58.920 --> 00:01:59.420
package.

42
00:02:00.160 --> 00:02:08.820
That NuGet package is Microsoft Semantic Kernel Connectors

43
00:02:08.820 --> 00:02:10.620
SQLite Vector Store.

44
00:02:11.860 --> 00:02:15.080
So this is part of something called Microsoft

45
00:02:15.080 --> 00:02:19.620
Extensions.VectorData. It just has a little funny

46
00:02:19.620 --> 00:02:21.920
name because this is actually the old version

47
00:02:21.920 --> 00:02:24.400
of Agent Framework, but it's only by name.

48
00:02:25.020 --> 00:02:27.020
It has nothing to do with the old

49
00:02:27.020 --> 00:02:27.380
stuff.

50
00:02:28.880 --> 00:02:31.380
But this is our implementation, and they have

51
00:02:31.380 --> 00:02:33.820
other connectors to the other vector stores.

52
00:02:35.560 --> 00:02:37.260
So what we're going to do is we're

53
00:02:37.260 --> 00:02:40.240
going to make a connection string to a

54
00:02:40.240 --> 00:02:40.980
SQLite.

55
00:02:41.120 --> 00:02:43.600
So that's just writing data source and then

56
00:02:43.600 --> 00:02:44.960
a path to some place.

57
00:02:45.300 --> 00:02:47.460
In my case, I'm putting it down in

58
00:02:47.460 --> 00:02:50.220
my temp folder.

59
00:02:51.640 --> 00:02:53.120
And then I'm going to new up a

60
00:02:53.120 --> 00:02:53.640
vector store.

61
00:02:54.120 --> 00:02:56.780
In this case, it's Microsoft Semantic Kernel Connectors

62
00:02:56.780 --> 00:02:59.320
Vector Store SQLite.

63
00:03:00.060 --> 00:03:03.480
And I'm putting in the connection string, and

64
00:03:03.480 --> 00:03:08.120
then I'm making a vector store options object,

65
00:03:08.500 --> 00:03:10.900
which I give the generator.

66
00:03:11.840 --> 00:03:14.920
So we're hooking this up to this because

67
00:03:14.920 --> 00:03:16.700
then it can generate on its own.

68
00:03:17.140 --> 00:03:22.300
We could technically sit down and take any

69
00:03:22.300 --> 00:03:25.140
kind of thing that can support vectors and

70
00:03:25.140 --> 00:03:28.140
begin to generate the vectors ourselves and put

71
00:03:28.140 --> 00:03:31.920
them in using the SQL language or the

72
00:03:31.920 --> 00:03:33.820
language of the vector store.

73
00:03:34.620 --> 00:03:37.220
But this is just a convenient way to

74
00:03:37.220 --> 00:03:38.540
not do that.

75
00:03:39.400 --> 00:03:41.760
So we have this vector store now.

76
00:03:42.100 --> 00:03:43.200
We could have made others.

77
00:03:43.440 --> 00:03:45.040
So, for example, if we wanted to have

78
00:03:45.040 --> 00:03:48.500
Azure AI Search, which is a powerful but

79
00:03:48.500 --> 00:03:51.520
quite expensive version of a vector store.

80
00:03:52.320 --> 00:03:54.100
And in that, we would just need to

81
00:03:54.100 --> 00:03:56.980
give our endpoint and our key in order

82
00:03:56.980 --> 00:03:57.680
to do this.

83
00:03:58.140 --> 00:04:00.820
If we wanted to use SQL Server, it

84
00:04:00.820 --> 00:04:03.460
works from SQL Server 2025 and forward.

85
00:04:04.200 --> 00:04:05.940
We would just need a connection string.

86
00:04:06.600 --> 00:04:08.680
And if we wanted to use Cosmos DB,

87
00:04:08.880 --> 00:04:10.920
who can also do it, we would need

88
00:04:10.920 --> 00:04:13.500
a connection string, the database name, and tell

89
00:04:13.500 --> 00:04:15.079
a little about serialisation.

90
00:04:17.519 --> 00:04:20.060
So all of them is just about some

91
00:04:20.060 --> 00:04:22.220
connection string to get something up and running,

92
00:04:22.340 --> 00:04:23.900
but they all turn out to be a

93
00:04:23.900 --> 00:04:24.420
vector store.

94
00:04:24.700 --> 00:04:26.800
So we are having a general system.

95
00:04:29.000 --> 00:04:30.780
And then we are going to make what

96
00:04:30.780 --> 00:04:31.840
is called a collection.

97
00:04:32.600 --> 00:04:34.040
So we're getting a collection.

98
00:04:34.040 --> 00:04:36.260
We are telling that the primary key is

99
00:04:36.260 --> 00:04:36.660
GWT.

100
00:04:37.860 --> 00:04:42.160
And our data is equal to this object

101
00:04:42.160 --> 00:04:42.940
we have here.

102
00:04:43.960 --> 00:04:46.340
I didn't mention this one up here was

103
00:04:46.340 --> 00:04:47.900
just a question and an answer.

104
00:04:49.040 --> 00:04:51.600
But this down here is a bit more

105
00:04:51.600 --> 00:04:54.060
in that we are going to tell that

106
00:04:54.060 --> 00:04:57.200
we have an object that should represent a

107
00:04:57.200 --> 00:04:58.960
record in our vector store.

108
00:04:59.880 --> 00:05:02.000
In a SQL, it's a table.

109
00:05:02.660 --> 00:05:07.140
But in Azure AI Search, it's an index.

110
00:05:07.580 --> 00:05:11.460
So it's called collection just to be more

111
00:05:11.460 --> 00:05:11.800
generic.

112
00:05:12.400 --> 00:05:13.960
But in a SQL Server, it's just a

113
00:05:13.960 --> 00:05:14.180
table.

114
00:05:16.080 --> 00:05:17.880
And then we're going to tell we have

115
00:05:17.880 --> 00:05:21.580
an ID, which is the key of this.

116
00:05:22.320 --> 00:05:24.240
And then we can put in one or

117
00:05:24.240 --> 00:05:26.520
more pieces of data, because we haven't really

118
00:05:26.520 --> 00:05:28.060
talked about this yet.

119
00:05:28.660 --> 00:05:31.600
But whenever we do a vector similarity search,

120
00:05:31.800 --> 00:05:33.560
once we have found the right search, we

121
00:05:33.560 --> 00:05:36.700
actually need the real data to give back

122
00:05:36.700 --> 00:05:37.400
to the LLM.

123
00:05:37.640 --> 00:05:39.860
It doesn't really want to have the vector.

124
00:05:40.360 --> 00:05:42.120
It just want to have the data that

125
00:05:42.120 --> 00:05:45.500
was similar to it in its original form.

126
00:05:45.920 --> 00:05:48.100
So we're saving the question and the answer.

127
00:05:48.860 --> 00:05:51.140
And we are putting in vector store data

128
00:05:51.140 --> 00:05:51.500
here.

129
00:05:52.480 --> 00:05:53.900
And if you have a lot of data,

130
00:05:53.980 --> 00:05:56.400
you can put in to make it indexes

131
00:05:56.400 --> 00:05:58.620
and give it new names if need be.

132
00:06:00.320 --> 00:06:02.380
The final one we need to have is

133
00:06:02.380 --> 00:06:03.680
a vector store vector.

134
00:06:04.080 --> 00:06:06.620
So the vector we have, how many dimensions

135
00:06:06.620 --> 00:06:10.400
it is, and what should represent the vector.

136
00:06:10.620 --> 00:06:12.160
In our case, we want to have that

137
00:06:12.160 --> 00:06:14.700
the question and the answer is the vector.

138
00:06:15.420 --> 00:06:18.860
So we get it in Q, question dash

139
00:06:18.860 --> 00:06:19.720
A, answer.

140
00:06:19.960 --> 00:06:22.240
That would be what we want to embed.

141
00:06:24.760 --> 00:06:28.680
So when we do that, we get this

142
00:06:28.680 --> 00:06:30.440
back, and we can give it a name.

143
00:06:30.760 --> 00:06:32.400
So in our case, since it's a SQL,

144
00:06:32.720 --> 00:06:34.540
it will be the table name.

145
00:06:35.000 --> 00:06:37.400
In an Azure AI search, it would be

146
00:06:37.400 --> 00:06:38.740
the index name.

147
00:06:40.700 --> 00:06:43.040
So once we have one of these, we

148
00:06:43.040 --> 00:06:46.560
can call a method called ensure collection exists,

149
00:06:47.440 --> 00:06:48.940
meaning a creation of it.

150
00:06:49.020 --> 00:06:51.440
So in, again, a SQL, it will be

151
00:06:51.440 --> 00:06:52.220
create table.

152
00:06:53.740 --> 00:06:55.660
And in an Azure AI search, it will

153
00:06:55.660 --> 00:06:56.860
be create index.

154
00:06:59.060 --> 00:07:02.700
So now we have it, our table, and

155
00:07:02.700 --> 00:07:05.020
we can ask if we want to import

156
00:07:05.020 --> 00:07:05.420
data.

157
00:07:06.340 --> 00:07:08.080
So I just put it in so we

158
00:07:08.080 --> 00:07:10.280
don't need to import every single time.

159
00:07:10.840 --> 00:07:12.720
But if we run it the first time

160
00:07:12.720 --> 00:07:20.400
here, we can see it comes and asks

161
00:07:20.400 --> 00:07:22.020
us, do we want to import data?

162
00:07:25.160 --> 00:07:28.480
And just so it's easy here, normally you

163
00:07:28.480 --> 00:07:30.580
would do a little more data manipulation.

164
00:07:31.000 --> 00:07:33.200
I will talk a little about that in

165
00:07:33.200 --> 00:07:33.800
one second.

166
00:07:34.660 --> 00:07:37.640
But in this case, just to ensure that

167
00:07:37.640 --> 00:07:39.180
we get rid of all the old data,

168
00:07:39.720 --> 00:07:41.820
I just say we actually delete the table

169
00:07:41.820 --> 00:07:44.160
again and recreate it.

170
00:07:44.200 --> 00:07:45.580
Then we are sure that it's empty.

171
00:07:46.060 --> 00:07:48.300
We can actually go in and work with

172
00:07:48.300 --> 00:07:49.940
the data, delete certain things.

173
00:07:50.960 --> 00:07:55.260
But my main problem, if I just added

174
00:07:55.260 --> 00:07:57.060
new data all the time, is that right

175
00:07:57.060 --> 00:07:59.380
now my ID is a new grid every

176
00:07:59.380 --> 00:07:59.980
single time.

177
00:08:00.820 --> 00:08:04.880
Had it been something that were fixed for

178
00:08:04.880 --> 00:08:07.140
my records, I could just run this again

179
00:08:07.140 --> 00:08:10.280
and again and absurd it, meaning if it

180
00:08:10.280 --> 00:08:12.500
already exists, it would update it instead.

181
00:08:15.460 --> 00:08:17.720
So I'm going to delete and create.

182
00:08:18.320 --> 00:08:20.500
And then we are going to go to

183
00:08:20.500 --> 00:08:22.300
our 10 knowledge bases.

184
00:08:23.980 --> 00:08:26.420
And we are just going to say absurd

185
00:08:26.420 --> 00:08:30.240
async with this new record that we want.

186
00:08:30.660 --> 00:08:32.059
So we just give it the ID, the

187
00:08:32.059 --> 00:08:33.280
question, and the answer.

188
00:08:34.179 --> 00:08:37.460
And behind the scenes, absurd will go in

189
00:08:37.460 --> 00:08:41.500
and do our embedding, like we saw in

190
00:08:41.500 --> 00:08:42.400
the previous lecture.

191
00:08:43.300 --> 00:08:46.020
We can actually send the embeddings in to

192
00:08:46.020 --> 00:08:47.400
absurd if we want to.

193
00:08:47.400 --> 00:08:49.080
But this is just an easier way.

194
00:08:50.740 --> 00:08:53.540
So it will take a little time, because

195
00:08:53.540 --> 00:08:56.540
every time we run this, we go up

196
00:08:56.540 --> 00:08:59.360
into Azure and do our embedding.

197
00:09:00.840 --> 00:09:05.320
But if we run it, we now have

198
00:09:05.320 --> 00:09:06.540
our 10 embeddings in.

199
00:09:07.760 --> 00:09:10.680
And what I do down here, let's try

200
00:09:10.680 --> 00:09:12.120
and rerun it so we can see what

201
00:09:12.120 --> 00:09:12.840
this is about.

202
00:09:14.300 --> 00:09:15.720
Let's just say no.

203
00:09:15.720 --> 00:09:18.520
We can also list our data.

204
00:09:18.820 --> 00:09:20.160
So there is a get async.

205
00:09:20.320 --> 00:09:22.300
It's not like we can write SQL against

206
00:09:22.300 --> 00:09:25.040
it, because again, this is a generic setup

207
00:09:25.040 --> 00:09:30.360
against indexes, SQLs, all kinds of ways of

208
00:09:30.360 --> 00:09:31.800
implementing a vector store.

209
00:09:32.160 --> 00:09:34.320
So we need to do a get async

210
00:09:34.320 --> 00:09:37.100
where we do a small func record.

211
00:09:37.680 --> 00:09:39.440
And in our case, I'm just saying give

212
00:09:39.440 --> 00:09:43.320
me all records that doesn't have the empty

213
00:09:43.320 --> 00:09:45.520
GWT, meaning all of them.

214
00:09:46.180 --> 00:09:48.080
And here I'm setting how many records do

215
00:09:48.080 --> 00:09:48.700
I want back.

216
00:09:48.840 --> 00:09:50.380
I want as many as possible.

217
00:09:52.060 --> 00:09:54.240
And doing that, I will get my first

218
00:09:54.240 --> 00:09:55.000
record back.

219
00:09:55.440 --> 00:09:59.980
So the first record here is our question

220
00:09:59.980 --> 00:10:00.840
about Wi-Fi.

221
00:10:01.440 --> 00:10:02.200
Print it out.

222
00:10:02.700 --> 00:10:03.260
Next.

223
00:10:03.460 --> 00:10:05.560
So we're just doing a for each on

224
00:10:05.560 --> 00:10:06.140
all the data.

225
00:10:07.100 --> 00:10:09.640
Behind the scenes, this implementation will use a

226
00:10:09.640 --> 00:10:13.940
SQL in order to get this information, while

227
00:10:13.940 --> 00:10:16.240
an Azure AI search will use their API

228
00:10:16.240 --> 00:10:17.480
to get the data instead.

229
00:10:18.500 --> 00:10:21.060
So we just get our 10 questions out

230
00:10:21.060 --> 00:10:23.300
here just for us to see that they

231
00:10:23.300 --> 00:10:23.840
are in there.

232
00:10:24.740 --> 00:10:28.480
We could also go to the SQLite database,

233
00:10:28.720 --> 00:10:32.480
but it has a slight odd way of

234
00:10:32.480 --> 00:10:37.080
storing the vectors, which again is abstracted away

235
00:10:37.080 --> 00:10:37.620
from us.

236
00:10:37.720 --> 00:10:40.040
In SQL, it's just a column, but in

237
00:10:40.040 --> 00:10:43.600
SQLite, it's some more extra tables that have

238
00:10:43.600 --> 00:10:47.440
the data for some reason that they have

239
00:10:47.440 --> 00:10:47.740
chosen.

240
00:10:48.160 --> 00:10:49.660
It doesn't really matter to us.

241
00:10:50.140 --> 00:10:53.620
We now have our vector store.

242
00:10:53.900 --> 00:10:56.920
So with our data put in, so now

243
00:10:56.920 --> 00:10:59.140
we should be able to actually finish this

244
00:10:59.600 --> 00:11:01.760
and begin to search against it as well.
