Skip to content

Commit 04206dd

Browse files
committed
update to v1.1.3
fix serious bug when streaming request
1 parent d41fab2 commit 04206dd

8 files changed

Lines changed: 98 additions & 51 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ or by yarn:
3232
yarn add agently
3333
```
3434

35-
> ⚠️ Latest Version on NPM is 1.1.2-1, if you came across trouble unexpected, try update first.
35+
> ⚠️ Latest Version on NPM is 1.1.3, if you came across trouble unexpected, try update first.
3636
3737
## TOO MUCH WORDS, JUST SHOW ME THE CODE
3838

README_CN.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ npm安装方法:`npm install agently`
3535

3636
yarn安装方法:`yarn add agently`
3737

38-
> 在npm上当前最新版本是:1.1.2-1,只要你还在使用Agently v1版本,可以放心update,我会保证本文档中提到的所有使用用例的可用性
38+
> 在npm上当前最新版本是:1.1.3,只要你还在使用Agently v1版本,可以放心update,我会保证本文档中提到的所有使用用例的可用性
3939
4040
## 说明好长不想看,能不能直接上代码?
4141

lib/LLM.js

Lines changed: 29 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -217,36 +217,40 @@ class LLMRequest {
217217
let streamingBuffer = '',
218218
role = ''
219219
responseResult.data.on(this.llm.eventMapping['data'], data => {
220+
//console.log(data.toString())
220221
if (data && data.toString() && data.toString() !== '') {
221-
const extractResult =
222-
extract
223-
? extract(findJSONString(data.toString()))
224-
: JSON.parse(findJSONString(data.toString()))
225-
if (!extractResult.type) extractResult = { type: 'data', data: extractResult }
226-
const sendResult = {
227-
type: extractResult.type,
228-
data: extractResult.data,
229-
}
230-
if (sendResult.type !== 'done') {
231-
if (typeof(sendResult?.data?.delta?.role) === 'string') role = sendResult?.data.delta.role
232-
if (typeof(sendResult?.data?.delta?.content) === 'string') {
233-
const delta = sendResult.data.delta.content
234-
streamingBuffer += delta
235-
if (delta.length > 10) {
236-
for (let i = 0; i < delta.length; i += 10) {
237-
let tempResult = {
238-
type: sendResult.type,
239-
data: sendResult.data,
222+
let JSONData = findJSONString(data.toString())
223+
if (!JSON.parse(JSONData).emptyChunk) {
224+
let extractResult =
225+
extract
226+
? extract(JSONData)
227+
: JSON.parse(JSONData)
228+
if (!extractResult || !extractResult?.type) extractResult = { type: 'data', data: '' }
229+
const sendResult = {
230+
type: extractResult.type,
231+
data: extractResult.data,
232+
}
233+
if (sendResult.type !== 'done') {
234+
if (typeof(sendResult?.data?.delta?.role) === 'string') role = sendResult?.data.delta.role
235+
if (sendResult?.data?.delta?.content) {
236+
const delta = sendResult.data.delta.content.toString()
237+
streamingBuffer += delta
238+
if (delta.length > 10) {
239+
for (let i = 0; i < delta.length; i += 10) {
240+
let tempResult = {
241+
type: sendResult.type,
242+
data: sendResult.data,
243+
}
244+
tempResult.data.delta.content = delta.substr(i, 10)
245+
finalResult.emit(tempResult.type, tempResult.data)
240246
}
241-
tempResult.data.delta.content = delta.substr(i, 10)
242-
finalResult.emit(tempResult.type, tempResult.data)
247+
} else {
248+
finalResult.emit(sendResult.type, sendResult.data)
243249
}
244-
} else {
245-
finalResult.emit(sendResult.type, sendResult.data)
246250
}
251+
} else {
252+
finalResult.emit('finish', { role: role, content: streamingBuffer })
247253
}
248-
} else {
249-
finalResult.emit('finish', { role: role, content: streamingBuffer })
250254
}
251255
}
252256
})

lib/ProcessUnit.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ class ProcessRequest {
185185
])
186186
}
187187
//Init Runtime
188-
this.initRuntime()
188+
this.initRuntime()
189189
//Final Response
190190
return finalResponse
191191
//<streaming>
@@ -242,6 +242,7 @@ class ProcessRequest {
242242
buffer = ''
243243
} else {
244244
buffer = buffer.replace('<\/$$$>')
245+
//console.log(`[${currentNode}]: done`)
245246
responseEvent.emit(currentNode, { done: true }, segment)
246247
segments.push({ ...segment })
247248
segment = { node: null, content: '' }

lib/format.js

Lines changed: 50 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,11 @@ function toJSONString (origin, layer = 0) {
1414
for (let key in origin) {
1515
content += `${ insertTab(layer + 1) }"${ key }": ${ toJSONString(origin[key], layer + 1) }\n`
1616
}
17-
content += `${ insertTab(layer) }},`
17+
if (layer > 0) {
18+
content += `${ insertTab(layer) }},`
19+
} else {
20+
content += `}`
21+
}
1822
return content
1923
} else {
2024
return typeof(origin) === 'string'
@@ -34,31 +38,64 @@ function extractWarpedContent (origin) {
3438
return finalResult
3539
}
3640

37-
//Thanks to GPT 4
38-
function findJSONString(str) {
41+
/*function findJSONString(str) {
3942
let openBraces = 0;
4043
let closeBraces = 0;
44+
let openSquareBrackets = 0;
45+
let closeSquareBrackets = 0;
4146
let jsonStartIndex;
47+
let insideQuotes = false;
4248
4349
for (let i = 0; i < str.length; i++) {
4450
const char = str[i];
4551
46-
if (char === '{') {
47-
if (openBraces === 0) {
48-
jsonStartIndex = i;
49-
}
50-
openBraces++;
51-
} else if (char === '}') {
52-
closeBraces++;
52+
if (char === '"') {
53+
insideQuotes = !insideQuotes;
5354
}
5455
55-
if (openBraces > 0 && openBraces === closeBraces) {
56-
return str.slice(jsonStartIndex, i+1);
56+
if (!insideQuotes) {
57+
if (char === '{') {
58+
if (openBraces === 0) {
59+
jsonStartIndex = i;
60+
}
61+
openBraces++;
62+
} else if (char === '}') {
63+
closeBraces++;
64+
} else if (char === '[') {
65+
if (openSquareBrackets === 0 && openBraces === 0) {
66+
jsonStartIndex = i;
67+
}
68+
openSquareBrackets++;
69+
} else if (char === ']') {
70+
closeSquareBrackets++;
71+
}
72+
73+
if ( (openBraces > 0 || openSquareBrackets > 0) && (openBraces === closeBraces) && (openSquareBrackets === closeSquareBrackets)) {
74+
return str.slice(jsonStartIndex, i+1);
75+
}
5776
}
5877
}
5978
6079
//throw new Error('Invalid JSON string');
61-
return '{}'
80+
return JSON.stringify({ emptyChunk: true })
81+
}*/
82+
function findJSONString(str) {
83+
for (let end = str.length; end > 0; end--) {
84+
for (let start = 0; start + end <= str.length; start++) {
85+
try {
86+
const substring = str.substring(start, start + end);
87+
if ((substring.startsWith("{") && substring.endsWith("}")) || (substring.startsWith("[") && substring.endsWith("]"))) {
88+
const potentialJson = JSON.parse(substring);
89+
return JSON.stringify(potentialJson);
90+
}
91+
} catch (err) {
92+
// Ignore errors as they simply mean the current substring is not valid JSON
93+
}
94+
}
95+
}
96+
97+
//throw new Error("No valid JSON found in input string");
98+
return JSON.stringify({ emptyChunk: true })
6299
}
63100

64101
exports.toJSONString = toJSONString

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "agently",
3-
"version": "1.1.2-1",
3+
"version": "1.1.3",
44
"description": "🤵 Agently is a framework helps developers to create amazing LLM based applications.\n🎭 You can use it to create an LLM bansed agent instance with role set and memory easily.\n⚙️ You can use Agently agent instance just like an async function and put it anywhere in your code.\n🧩 With the easy-to-plug-in design, you can easily append new LLM API/private API/memory management methods/skills to your Agently agent instance.\n⚠️ Notice: Agently is a node.js package only works on the server-side.",
55
"main": "index.js",
66
"scripts": {

preset/LLM.js

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,8 @@ module.exports = (Agently) => {
8383
try {
8484
return { type: 'data', data: JSON.parse(data)?.choices[0] || '' }
8585
} catch (e) {
86-
console.error(e)
86+
return { type: 'data', data: '' }
87+
//console.error(e)
8788
}
8889
} else {
8990
return { type: 'done', data: null }
@@ -169,8 +170,13 @@ module.exports = (Agently) => {
169170
//when streaming is done: return { type: 'done', data: null }
170171
.extractStreamingData(
171172
data => {
172-
if (data !== '[DONE]\n\n') {
173-
return { type: 'data', data: JSON.parse(data).choices[0] }
173+
if (data && data !== '[DONE]\n\n') {
174+
try {
175+
return { type: 'data', data: JSON.parse(data)?.choices[0] || '' }
176+
} catch (e) {
177+
return { type: 'data', data: '' }
178+
//console.error(e)
179+
}
174180
} else {
175181
return { type: 'done', data: null }
176182
}

preset/prefix.js

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -130,9 +130,8 @@ module.exports = (Agently) => {
130130
content += '\n'
131131
if (prompt.multiOutput.length > 0) {
132132
content += `# OUTPUT FORMAT\n\n` +
133-
`## RULE\nEach output block must be warp by tag "<$$$node={nodeValue}>...</$$$>"!\n` +
134-
`Output block content must remove "\`\`\`" warp!\n\n` +
135-
`## COMPLETE OUTPUT CONTENT\n`
133+
`## RULE\nEach output block must be warp by tag "<$$$node={nodeValue}>...</$$$>"!\n\n` +
134+
`## FULL OUTPUT CONTENT\n`
136135
for (let i = 0; i < prompt.multiOutput.length; i++) {
137136
content += `<$$$node=${ prompt.multiOutput[i].title }>\n`
138137
if (!prompt.multiOutput[i].type) {
@@ -143,9 +142,9 @@ module.exports = (Agently) => {
143142
}
144143
}
145144
if (prompt.multiOutput[i].type === 'JSON') {
146-
content += `${ format.toJSONString(prompt.multiOutput[i].desc) }\n`
145+
content += `TYPE: ${ prompt.multiOutput[i].type } can be parsed in Python\n\nFORMAT DEFINITION:\n\n\`\`\`${ prompt.multiOutput[i].type }\n${ format.toJSONString(prompt.multiOutput[i].desc) }\n\`\`\`\n\n`
147146
} else {
148-
content += `${ prompt.multiOutput[i].desc }\n`
147+
content += `\`\`\`${ prompt.multiOutput[i].type }\n${ prompt.multiOutput[i].desc }\n\`\`\`\n\n`
149148
}
150149
content += `</$$$>\n\n`
151150
}
@@ -159,7 +158,7 @@ module.exports = (Agently) => {
159158
}
160159
}
161160
if (prompt.output.type === 'JSON') {
162-
content += `TYPE: ${ prompt.output.type }\n\nFORMAT DEFINITION:\n\n\`\`\`${ prompt.output.type }\n${ format.toJSONString(prompt.output.desc) }\n\`\`\`\n\n`
161+
content += `TYPE: ${ prompt.output.type } can be parsed in Python\n\nFORMAT DEFINITION:\n\n\`\`\`${ prompt.output.type }\n${ format.toJSONString(prompt.output.desc) }\n\`\`\`\n\n`
163162
} else {
164163
content += `\`\`\`${ prompt.output.type }\n${ prompt.output.desc }\n\`\`\`\n\n`
165164
}

0 commit comments

Comments
 (0)