Update README.md
Browse files
README.md
CHANGED
@@ -7,11 +7,58 @@ tags:
|
|
7 |
|
8 |
---
|
9 |
|
10 |
-
#
|
11 |
|
12 |
-
This is a [sentence-transformers](https://www.SBERT.net) model: It maps
|
13 |
|
14 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
15 |
|
16 |
## Usage (Sentence-Transformers)
|
17 |
|
@@ -33,24 +80,9 @@ print(embeddings)
|
|
33 |
```
|
34 |
|
35 |
|
36 |
-
|
37 |
-
## Evaluation Results
|
38 |
-
|
39 |
-
<!--- Describe how your model was evaluated -->
|
40 |
-
|
41 |
-
For an automated evaluation of this model, see the *Sentence Embeddings Benchmark*: [https://seb.sbert.net](https://seb.sbert.net?model_name={MODEL_NAME})
|
42 |
-
|
43 |
-
|
44 |
## Training
|
45 |
The model was trained with the parameters:
|
46 |
|
47 |
-
**DataLoader**:
|
48 |
-
|
49 |
-
`torch.utils.data.dataloader.DataLoader` of length 1321 with parameters:
|
50 |
-
```
|
51 |
-
{'batch_size': 1280, 'sampler': 'torch.utils.data.sampler.RandomSampler', 'batch_sampler': 'torch.utils.data.sampler.BatchSampler'}
|
52 |
-
```
|
53 |
-
|
54 |
**Loss**:
|
55 |
|
56 |
`sentence_transformers.losses.TripletLoss.TripletLoss` with parameters:
|
@@ -77,6 +109,10 @@ Parameters of the fit()-Method:
|
|
77 |
}
|
78 |
```
|
79 |
|
|
|
|
|
|
|
|
|
80 |
|
81 |
## Full Model Architecture
|
82 |
```
|
@@ -86,10 +122,18 @@ SentenceTransformer(
|
|
86 |
(2): Asym(
|
87 |
(dialog-0): Dense({'in_features': 768, 'out_features': 1536, 'bias': True, 'activation_function': 'torch.nn.modules.activation.Tanh'})
|
88 |
(dialog-1): Dense({'in_features': 1536, 'out_features': 1536, 'bias': True, 'activation_function': 'torch.nn.modules.activation.Tanh'})
|
89 |
-
(dialog-2):
|
|
|
|
|
|
|
|
|
90 |
(fact-0): Dense({'in_features': 768, 'out_features': 1536, 'bias': True, 'activation_function': 'torch.nn.modules.activation.Tanh'})
|
91 |
(fact-1): Dense({'in_features': 1536, 'out_features': 1536, 'bias': True, 'activation_function': 'torch.nn.modules.activation.Tanh'})
|
92 |
-
(fact-2):
|
|
|
|
|
|
|
|
|
93 |
)
|
94 |
)
|
95 |
```
|
|
|
7 |
|
8 |
---
|
9 |
|
10 |
+
# DFE (Dialog Fact Encoder)
|
11 |
|
12 |
+
This is a [sentence-transformers](https://www.SBERT.net) model: It maps "dialog" & "facts" to a 768 dimensional dense vector space and can be used for tasks like clustering or semantic search.
|
13 |
|
14 |
+
The Dialog Fact Encoder (DFE) is an embedding model trained to capture semantic relevance between conversational dialog turns and factual statements. It builds upon the BGE embedding model by adding a merge layer that transforms the embeddings based on whether the input text is a "dialog" or "fact".
|
15 |
+
|
16 |
+
Specifically, dialog inputs pass through additional dense layers to project the embeddings into a space optimized for comparing dialog turns. Similarly, factual inputs pass through separate dense layers to transform the embeddings for relevance matching against dialogs.
|
17 |
+
|
18 |
+
This allows DFE to embed dialogs and facts into a joint relevance space without needing to generate explicit search queries. DFE enables low-latency approximate matching of relevant facts to dialog turns, while avoiding the high computational cost of query generation models.
|
19 |
+
|
20 |
+
The model was trained using a triplet loss to pull dialog embeddings closer to relevant fact embeddings, while pushing non-relevant pairs further apart. This helps the model learn the nuanced semantics needed to assess relevance between dialogs and facts.
|
21 |
+
|
22 |
+
DFE provides an efficient way to embed variable conversational dialog into a relevance space with factual statements. This enables real-time semantic search over knowledge without expensive query generation.
|
23 |
+
|
24 |
+
## Background
|
25 |
+
|
26 |
+
So what's _Dialog-Fact Encoder_?
|
27 |
+
|
28 |
+
It is a new model trained by the Julep AI team to match (possibly) relevant facts to a dialog. It is an embedding model which means that it takes text as an input and outputs an embedding vector (a list of float numbers). In DFE's case, it takes an extra parameter "type" which can be either "dialog" or "fact".
|
29 |
+
|
30 |
+
A regular embedding model like openai's text-embedding-ada-2 does not distinguish between different types and gives vectors that can then be used for calculating similarity. These models are great for building search because comparing vectors is relatively cheap so for a database (of say product descriptions), you can compute vectors for every row beforehand and then when a query comes in (like: "Winter coats for women"), calculate the query's embeddings and find items using vector similarity.
|
31 |
+
|
32 |
+
Unfortunately, this does not work for dialog because conversational statements and turns within a dialog are typically not in the format of a "query". Take this case for example:
|
33 |
+
|
34 |
+
**Database**:
|
35 |
+
1. Diwank likes Sushi.
|
36 |
+
2. Ishita does not like unnecessarily-pricey places restaurants
|
37 |
+
3. Diwank likes cooking.
|
38 |
+
4. Ishita is terrible at cooking.
|
39 |
+
5. Diwank loves to eat Ishita's head.
|
40 |
+
|
41 |
+
**Dialog**:
|
42 |
+
> Diwank: Hey, what are we eating for dinner today?
|
43 |
+
> Ishita: Already? I thought we just ate lol
|
44 |
+
> Diwank: Yeah, some of us work hard and get hungy
|
45 |
+
> Ishita: Okay, what do you want to eat then?
|
46 |
+
> Diwank: I want to eat out but I am thinking of something light.
|
47 |
+
|
48 |
+
Now, a text/vector/hybrid search would probably match all 5 facts to this conversation but, as you can see, only facts 1 and 2 are relevant. The only way to get the correct fact, right now, is to ask an LLM like gpt-3.5 to "generate a query" for querying the database and then using that for similarity. Unfortunately, there are three big problems with that:
|
49 |
+
- It adds latency and cost.
|
50 |
+
- You have to figure out "when" to run this process and retrieve (which is hard).
|
51 |
+
- The prompt for generating the query will have to be customized for every use case because the prompt has to "know" what is "query-able". So for example, in this case above, we would have to specify that you can write a query to search preferences of Diwank and Ishita from the database.
|
52 |
+
|
53 |
+
Here's where DFE comes in. The insight here is that embeddings for a dialog have meaningful information to distinguish whether a fact is relevant or not (that is exactly how we can tell that Fact 1 and 2 are relevant and others are not in the example above because we can "see" the meaning of the dialog). Normal embedding models are only interested in "overall similarity" and they'd miss this nuance, especially for details that were NOT present in the dialog directly (for example, fact 1 mentions Sushi whereas no food items are specifically mentioned in the dialog).
|
54 |
+
|
55 |
+
So, if this information is already there in theory, how can we learn to connect embeddings of "facts" and "dialogues" based on relevance? DFE is trained to do exactly that. DFE is about learning this "relevance" transformation of a dialog so it matches similar facts.
|
56 |
+
|
57 |
+
DFE is a built upon BGE (currently the best state-of-the-art model for embeddings). It has the base embeddings from the original BGE model and then an added "merge" model layer. The base BGE model is actually left completely unchanged (because it already knows how to turn a passage into an embedding very well. We add the new layers to learn how to "transform" the input depending on what kind of passage it is (a dialog or a fact) in a way that "relevant" stuff is closer together in the embedding space.
|
58 |
+
|
59 |
+
This solves all of the three problems from the "query generation" method from earlier. Instead of generating a query using an LLM, you can store facts with their DFE embeddings in the database beforehand and then just embed the dialog using DFE and match. Since this operation is so much faster, you can basically do this on every turn without much hassle.
|
60 |
+
|
61 |
+
The "query generation" method is still far superior in quality but is too prohibitive (costly + slow) in normal circumstances and DFE solves that. :)
|
62 |
|
63 |
## Usage (Sentence-Transformers)
|
64 |
|
|
|
80 |
```
|
81 |
|
82 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
83 |
## Training
|
84 |
The model was trained with the parameters:
|
85 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
86 |
**Loss**:
|
87 |
|
88 |
`sentence_transformers.losses.TripletLoss.TripletLoss` with parameters:
|
|
|
109 |
}
|
110 |
```
|
111 |
|
112 |
+
## Evaluation Results
|
113 |
+
|
114 |
+
<!--- Describe how your model was evaluated -->
|
115 |
+
|
116 |
|
117 |
## Full Model Architecture
|
118 |
```
|
|
|
122 |
(2): Asym(
|
123 |
(dialog-0): Dense({'in_features': 768, 'out_features': 1536, 'bias': True, 'activation_function': 'torch.nn.modules.activation.Tanh'})
|
124 |
(dialog-1): Dense({'in_features': 1536, 'out_features': 1536, 'bias': True, 'activation_function': 'torch.nn.modules.activation.Tanh'})
|
125 |
+
(dialog-2): Dropout(
|
126 |
+
(dropout_layer): Dropout(p=0.1, inplace=False)
|
127 |
+
)
|
128 |
+
(dialog-3): Dense({'in_features': 1536, 'out_features': 1536, 'bias': True, 'activation_function': 'torch.nn.modules.activation.Tanh'})
|
129 |
+
(dialog-4): Dense({'in_features': 1536, 'out_features': 768, 'bias': True, 'activation_function': 'torch.nn.modules.activation.Tanh'})
|
130 |
(fact-0): Dense({'in_features': 768, 'out_features': 1536, 'bias': True, 'activation_function': 'torch.nn.modules.activation.Tanh'})
|
131 |
(fact-1): Dense({'in_features': 1536, 'out_features': 1536, 'bias': True, 'activation_function': 'torch.nn.modules.activation.Tanh'})
|
132 |
+
(fact-2): Dropout(
|
133 |
+
(dropout_layer): Dropout(p=0.1, inplace=False)
|
134 |
+
)
|
135 |
+
(fact-3): Dense({'in_features': 1536, 'out_features': 1536, 'bias': True, 'activation_function': 'torch.nn.modules.activation.Tanh'})
|
136 |
+
(fact-4): Dense({'in_features': 1536, 'out_features': 768, 'bias': True, 'activation_function': 'torch.nn.modules.activation.Tanh'})
|
137 |
)
|
138 |
)
|
139 |
```
|