Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/extensions/copilot/src/extension/prompt/common/streamingGrammar.ts
13399 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import { Iterable } from '../../../util/vs/base/common/iterator';
7
8
export interface IToken<S> {
9
state: S;
10
transitionTo?: S;
11
token: string;
12
}
13
14
/**
15
* Defines a grammar that moves the streaming response between states (S).
16
* You give it an initial state and then a map of states the grammar is in, to
17
* substrings that it looks for to move into a different state.
18
*/
19
export class StreamingGrammar<S extends string | number> {
20
public state: S;
21
private accumulator = '';
22
23
private currentEntries: [string, S][] = [];
24
25
/**
26
* A list of tokens seen so far. "tokens" are substrings of the `deltaText`.
27
* 'transitionTo' is set for tokens seen in the grammar when a state transiton happens.
28
*/
29
public readonly tokens: IToken<S>[] = [];
30
31
constructor(
32
initialState: S,
33
private readonly grammar: { [K in S]?: { [token: string]: S } },
34
) {
35
this.state = initialState;
36
this.currentEntries = Object.entries(grammar[initialState] || {});
37
}
38
39
/**
40
* Gets whether the given state was visited.
41
*/
42
public visited(state: S) {
43
return this.tokens.some(token => token.state === state);
44
}
45
46
/**
47
* Convenience function that accumulates the string of tokens between
48
* the given indices, optionally only for tokens in the given state.
49
*/
50
public accumulate(fromIndex = 0, toIndex = this.tokens.length, whenState?: S) {
51
let str = '';
52
for (let i = fromIndex; i < toIndex && i < this.tokens.length; i++) {
53
const token = this.tokens[i];
54
if (whenState !== undefined) {
55
if (token.state === whenState && !token.transitionTo) {
56
str += token.token;
57
}
58
} else {
59
str += token.token;
60
}
61
}
62
63
return str;
64
}
65
66
/** Appends text, returns the tokens that were added as a convenience. */
67
public append(deltaText: string): Iterable<IToken<S>> {
68
let maxLength = 0;
69
let found: { index: number; length: number; toState: S } | undefined;
70
const startIndex = this.tokens.length;
71
72
this.accumulator += deltaText;
73
for (const [key, toState] of this.currentEntries) {
74
const index = this.accumulator.indexOf(key);
75
if (index !== -1 && (!found || index < found.index)) {
76
found = { index, toState, length: key.length };
77
}
78
79
maxLength = Math.max(maxLength, key.length);
80
}
81
82
if (found) {
83
if (found.index > 0) {
84
this.tokens.push({ state: this.state, token: this.accumulator.slice(0, found.index) });
85
}
86
this.tokens.push({ state: this.state, token: this.accumulator.slice(found.index, found.index + found.length), transitionTo: found.toState });
87
88
const remainder = this.accumulator.slice(found.index + found.length);
89
this.state = found.toState;
90
this.currentEntries = Object.entries(this.grammar[found.toState] || {});
91
this.accumulator = '';
92
this.append(remainder);
93
} else if (this.accumulator.length > maxLength) {
94
// todo: we could use a boyer-moore-horspool lookup table to reduce
95
// the amoung of accumulated text we need to keep
96
this.tokens.push({ state: this.state, token: this.accumulator.slice(0, this.accumulator.length - maxLength) });
97
this.accumulator = this.accumulator.slice(this.accumulator.length - maxLength);
98
}
99
100
return Iterable.slice(this.tokens, startIndex);
101
}
102
103
public flush(): Iterable<IToken<S>> {
104
if (this.accumulator) {
105
this.tokens.push({ state: this.state, token: this.accumulator });
106
return Iterable.slice(this.tokens, -1);
107
}
108
109
return Iterable.empty();
110
}
111
}
112
113