Paul Bird commited on
Commit
5f14f33
1 Parent(s): ab1e40d

Upload 4 files

Browse files
Files changed (5) hide show
  1. .gitattributes +1 -0
  2. MiniLMv6.cs +158 -0
  3. MiniLMv6.onnx +3 -0
  4. MiniLMv6.sentis +3 -0
  5. vocab.txt +0 -0
.gitattributes CHANGED
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ MiniLMv6.sentis filter=lfs diff=lfs merge=lfs -text
MiniLMv6.cs ADDED
@@ -0,0 +1,158 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ using System.Collections.Generic;
2
+ using UnityEngine;
3
+ using Unity.Sentis;
4
+ using System.IO;
5
+ using System.Text;
6
+
7
+ /*
8
+ * Tiny Stories Inference Code
9
+ * ===========================
10
+ *
11
+ * Put this script on the Main Camera
12
+ *
13
+ * In Assets/StreamingAssets put:
14
+ *
15
+ * MiniLMv6.sentis
16
+ * vocab.txt
17
+ *
18
+ * Install package com.unity.sentis
19
+ *
20
+ */
21
+
22
+
23
+ public class MiniLM : MonoBehaviour
24
+ {
25
+ const BackendType backend = BackendType.GPUCompute;
26
+
27
+ string string1 = "That is a happy person"; // similarity = 1
28
+
29
+ //Choose a string to comapre string1 to:
30
+ string string2 = "That is a happy dog"; // similarity = 0.695
31
+ //string string2 = "That is a very happy person"; // similarity = 0.943
32
+ //string string2 = "Today is a sunny day"; // similarity = 0.257
33
+
34
+ //Special tokens
35
+ const int START_TOKEN = 101;
36
+ const int END_TOKEN = 102;
37
+
38
+ Ops ops;
39
+ ITensorAllocator allocator;
40
+
41
+ //Store the vocabulary
42
+ string[] tokens;
43
+
44
+ IWorker engine;
45
+
46
+ void Start()
47
+ {
48
+ allocator = new TensorCachingAllocator();
49
+ ops = WorkerFactory.CreateOps(backend, allocator);
50
+
51
+ tokens = File.ReadAllLines(Application.streamingAssetsPath + "/vocab.txt");
52
+
53
+ Model model = ModelLoader.Load(Application.streamingAssetsPath + "/MiniLMv6.sentis");
54
+
55
+ engine = WorkerFactory.CreateWorker(backend, model);
56
+
57
+ var tokens1 = GetTokens(string1);
58
+ var tokens2 = GetTokens(string2);
59
+
60
+ TensorFloat embedding1 = GetEmbedding(tokens1);
61
+ TensorFloat embedding2 = GetEmbedding(tokens2);
62
+
63
+ Debug.Log("Similarity Score: " + DotScore(embedding1, embedding2));
64
+ }
65
+
66
+ float DotScore(TensorFloat embedding1, TensorFloat embedding2)
67
+ {
68
+ using var prod = ops.Mul(embedding1, embedding2);
69
+ using var dot = ops.ReduceSum(prod, new int[] { 1 }, false);
70
+ dot.MakeReadable();
71
+ return dot[0];
72
+ }
73
+
74
+ TensorFloat GetEmbedding(List<int> tokens)
75
+ {
76
+ int N = tokens.Count;
77
+ using var input_ids = new TensorInt(new TensorShape(1, N), tokens.ToArray());
78
+ using var token_type_ids = new TensorInt(new TensorShape(1, N), new int[N]);
79
+ int[] mask = new int[N];
80
+ for (int i = 0; i < mask.Length; i++)
81
+ {
82
+ mask[i] = 1;
83
+ }
84
+ using var attention_mask = new TensorInt(new TensorShape(1, N), mask);
85
+
86
+ var inputs = new Dictionary<string, Tensor>
87
+ {
88
+ {"input_ids",input_ids },
89
+ {"token_type_ids", token_type_ids},
90
+ {"attention_mask", attention_mask }
91
+ };
92
+
93
+ engine.Execute(inputs);
94
+
95
+ var tokenEmbeddings = engine.PeekOutput("output") as TensorFloat;
96
+
97
+ return MeanPooling(tokenEmbeddings, attention_mask);
98
+ }
99
+
100
+ //Get average of token embeddings taking into account the attention mask
101
+ TensorFloat MeanPooling(TensorFloat tokenEmbeddings, TensorInt attentonMask)
102
+ {
103
+ using var mask0 = attentonMask.ShallowReshape(attentonMask.shape.Unsqueeze(-1)) as TensorInt;
104
+ using var maskExpanded = ops.Expand(mask0, tokenEmbeddings.shape);
105
+ using var maskExpandedF = ops.Cast(maskExpanded, DataType.Float) as TensorFloat;
106
+ using var D = ops.Mul(tokenEmbeddings, maskExpandedF);
107
+ using var A = ops.ReduceSum(D, new[] { 1 }, false);
108
+ using var C = ops.ReduceSum(maskExpandedF, new[] { 1 }, false);
109
+ using var B = ops.Clip(C, 1e-9f, float.MaxValue);
110
+ using var E = ops.Div(A, B);
111
+ using var F = ops.ReduceL2(E, new[] { 1 }, true);
112
+ return ops.Div(E, F);
113
+ }
114
+
115
+ List<int> GetTokens(string text)
116
+ {
117
+ //split over whitespace
118
+ string[] words = text.ToLower().Split(null);
119
+
120
+ var ids = new List<int>
121
+ {
122
+ START_TOKEN
123
+ };
124
+
125
+ string s = "";
126
+
127
+ foreach (var word in words)
128
+ {
129
+ int start = 0;
130
+ for(int i = word.Length; i >= 0;i--)
131
+ {
132
+ string subword = start == 0 ? word.Substring(start, i) : "##" + word.Substring(start, i-start);
133
+ int index = System.Array.IndexOf(tokens, subword);
134
+ if (index >= 0)
135
+ {
136
+ ids.Add(index);
137
+ s += subword + " ";
138
+ if (i == word.Length) break;
139
+ start = i;
140
+ i = word.Length + 1;
141
+ }
142
+ }
143
+ }
144
+
145
+ ids.Add(END_TOKEN);
146
+
147
+ Debug.Log("Tokenized sentece = " + s);
148
+
149
+ return ids;
150
+ }
151
+
152
+ private void OnDestroy()
153
+ {
154
+ engine?.Dispose();
155
+ ops?.Dispose();
156
+ allocator?.Dispose();
157
+ }
158
+ }
MiniLMv6.onnx ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:ef2a4bb91d5aff608459c2df78ba333404358b7809af564167e740a1e415e724
3
+ size 90984173
MiniLMv6.sentis ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:cd3cc73a83d426dd085c1839e587b6a7155ce91d6698f7ae2596a3f3cd02d1cf
3
+ size 90952597
vocab.txt ADDED
The diff for this file is too large to render. See raw diff