@baishuyun/chat-backend 0.0.10 → 0.0.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +3 -0
- package/CHANGELOG.md +16 -0
- package/ecosystem.config.cjs +4 -0
- package/package.json +4 -4
- package/src/app/main.ts +8 -3
- package/src/controllers/report/query/createQuerySuggestionTransStream.ts +54 -0
- package/src/controllers/report/query/model.ts +14 -0
- package/src/controllers/report/query/suggest.controller.ts +46 -0
- package/src/routes/report/report.route.ts +3 -0
package/.env.example
CHANGED
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# @baishuyun/chat-backend
|
|
2
2
|
|
|
3
|
+
## 0.0.12
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies
|
|
8
|
+
- @baishuyun/coze-provider@0.0.12
|
|
9
|
+
- @baishuyun/types@1.0.12
|
|
10
|
+
|
|
11
|
+
## 0.0.11
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- Updated dependencies
|
|
16
|
+
- @baishuyun/coze-provider@0.0.11
|
|
17
|
+
- @baishuyun/types@1.0.11
|
|
18
|
+
|
|
3
19
|
## 0.0.10
|
|
4
20
|
|
|
5
21
|
### Patch Changes
|
package/ecosystem.config.cjs
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@baishuyun/chat-backend",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.12",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -22,8 +22,8 @@
|
|
|
22
22
|
"parse-sse": "^0.1.0",
|
|
23
23
|
"pino": "^10.1.0",
|
|
24
24
|
"zod": "^4.1.13",
|
|
25
|
-
"@baishuyun/coze-provider": "0.0.
|
|
26
|
-
"@baishuyun/types": "1.0.
|
|
25
|
+
"@baishuyun/coze-provider": "0.0.12",
|
|
26
|
+
"@baishuyun/types": "1.0.12"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"@types/config": "^3.3.5",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"pm2": "^6.0.14",
|
|
35
35
|
"tsx": "^4.7.1",
|
|
36
36
|
"typescript": "^5.8.3",
|
|
37
|
-
"@baishuyun/typescript-config": "0.0.
|
|
37
|
+
"@baishuyun/typescript-config": "0.0.12"
|
|
38
38
|
},
|
|
39
39
|
"scripts": {
|
|
40
40
|
"dev": "cross-env NODE_ENV=development tsx watch src/index.ts",
|
package/src/app/main.ts
CHANGED
|
@@ -13,7 +13,12 @@ import { createReportRouter } from '../routes/report/report.route.js';
|
|
|
13
13
|
app.route('web/api/form', createFormRouter());
|
|
14
14
|
app.route('web/api/report', createReportRouter());
|
|
15
15
|
|
|
16
|
-
//
|
|
17
|
-
app.get('web/api/
|
|
18
|
-
return c.json({
|
|
16
|
+
// 基础健康检查
|
|
17
|
+
app.get('/web/api/health', (c) => {
|
|
18
|
+
return c.json({
|
|
19
|
+
status: 'ok',
|
|
20
|
+
timestamp: new Date().toISOString(),
|
|
21
|
+
uptime: process.uptime(),
|
|
22
|
+
service: 'hono-app',
|
|
23
|
+
});
|
|
19
24
|
});
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { type LanguageModelV2StreamPart } from '@ai-sdk/provider';
|
|
2
|
+
import { JSONParser } from '@streamparser/json';
|
|
3
|
+
import { type IQueryResult } from '@baishuyun/types';
|
|
4
|
+
import {
|
|
5
|
+
createJsonStreamTransformer,
|
|
6
|
+
type IParserCtx,
|
|
7
|
+
} from '../../../utils/createJsonStreamTransformer.js';
|
|
8
|
+
import { logger } from '../../../logger/index.js';
|
|
9
|
+
|
|
10
|
+
export interface ISuggestion {
|
|
11
|
+
t: string;
|
|
12
|
+
v: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
type suggestions = Array<ISuggestion>;
|
|
16
|
+
|
|
17
|
+
export const createQuerySuggestionTransformer = () => {
|
|
18
|
+
return createJsonStreamTransformer<suggestions>({
|
|
19
|
+
createJSONParser: createJSONParser,
|
|
20
|
+
onParseValue: handleParsedValue,
|
|
21
|
+
onParseError(error) {
|
|
22
|
+
logger.error('JSON parsing error in query transformer: ', error);
|
|
23
|
+
return '数据解析异常,请重试';
|
|
24
|
+
},
|
|
25
|
+
onErrorChunk(chunk) {
|
|
26
|
+
logger.error('Received error chunk in query transformer');
|
|
27
|
+
return '';
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
function createJSONParser(): JSONParser {
|
|
33
|
+
return new JSONParser({
|
|
34
|
+
stringBufferSize: undefined,
|
|
35
|
+
numberBufferSize: undefined,
|
|
36
|
+
separator: '',
|
|
37
|
+
paths: ['$.*'],
|
|
38
|
+
keepStack: true,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function handleParsedValue(ctx: IParserCtx<suggestions>): void {
|
|
43
|
+
const { parsedInfo, getResult, currentChunkId, deltaChunkEnqueuer: enqueueTextDelta, ctrl } = ctx;
|
|
44
|
+
const { value } = parsedInfo;
|
|
45
|
+
|
|
46
|
+
logger.debug('Parsed JSON value: ' + JSON.stringify(value));
|
|
47
|
+
|
|
48
|
+
enqueueTextDelta(
|
|
49
|
+
`${JSON.stringify(value)},`,
|
|
50
|
+
{ type: 'query-suggestion-parsed-info', result: JSON.stringify(getResult()) },
|
|
51
|
+
currentChunkId + 2,
|
|
52
|
+
true
|
|
53
|
+
);
|
|
54
|
+
}
|
|
@@ -2,6 +2,7 @@ import { createCoze } from '@baishuyun/coze-provider';
|
|
|
2
2
|
|
|
3
3
|
import config from 'config';
|
|
4
4
|
import { createQueryResultTransformer } from './createQueryTransformStream.js';
|
|
5
|
+
import { createQuerySuggestionTransformer } from './createQuerySuggestionTransStream.js';
|
|
5
6
|
|
|
6
7
|
export const createReportQueryModel = () => {
|
|
7
8
|
const reportQuery = createCoze({
|
|
@@ -15,3 +16,16 @@ export const createReportQueryModel = () => {
|
|
|
15
16
|
|
|
16
17
|
return reportQueryModel;
|
|
17
18
|
};
|
|
19
|
+
|
|
20
|
+
export const createQuerySuggestionModel = () => {
|
|
21
|
+
const reportQuery = createCoze({
|
|
22
|
+
apiKey: config.get<string>('agent.report.query.apiKey'),
|
|
23
|
+
baseURL: config.get<string>('agent.report.query.baseUrl'),
|
|
24
|
+
botId: config.get<string>('agent.report.query.botId'),
|
|
25
|
+
extraStreamTransformers: [createQuerySuggestionTransformer],
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
const reportQueryModel = reportQuery.chat('chat');
|
|
29
|
+
|
|
30
|
+
return reportQueryModel;
|
|
31
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { type Context } from 'hono';
|
|
2
|
+
import { convertToModelMessages, streamText, type UIMessage, generateId } from 'ai';
|
|
3
|
+
import { createReportQueryModel } from './model.js';
|
|
4
|
+
|
|
5
|
+
export const queryReportSuggest = async (c: Context) => {
|
|
6
|
+
let requestBody;
|
|
7
|
+
|
|
8
|
+
try {
|
|
9
|
+
const json = await c.req.json();
|
|
10
|
+
requestBody = json;
|
|
11
|
+
} catch (_) {
|
|
12
|
+
return c.json({ error: 'Invalid JSON' }, 400);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const uid = c.req.header('X-User-Id') || '';
|
|
16
|
+
const messages: UIMessage[] = requestBody.messages;
|
|
17
|
+
|
|
18
|
+
const forms = requestBody.forms || [];
|
|
19
|
+
|
|
20
|
+
const modelMessages = convertToModelMessages([
|
|
21
|
+
{
|
|
22
|
+
role: 'user',
|
|
23
|
+
parts: [
|
|
24
|
+
{
|
|
25
|
+
type: 'text',
|
|
26
|
+
text: JSON.stringify(forms),
|
|
27
|
+
},
|
|
28
|
+
],
|
|
29
|
+
},
|
|
30
|
+
]);
|
|
31
|
+
|
|
32
|
+
console.log('Final messages for query suggestion: ', JSON.stringify(modelMessages, null, 2));
|
|
33
|
+
|
|
34
|
+
const stream = streamText({
|
|
35
|
+
model: createReportQueryModel(),
|
|
36
|
+
messages: modelMessages,
|
|
37
|
+
includeRawChunks: true,
|
|
38
|
+
headers: {
|
|
39
|
+
'x-user-id': uid,
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
return stream.toUIMessageStreamResponse({
|
|
44
|
+
originalMessages: messages, // 建议添加,便于消息 ID 管理
|
|
45
|
+
});
|
|
46
|
+
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Hono } from 'hono';
|
|
2
2
|
import { queryReport } from '../../controllers/report/query/query.controller.js';
|
|
3
|
+
import { queryReportSuggest } from '../../controllers/report/query/suggest.controller.js';
|
|
3
4
|
|
|
4
5
|
export const createReportRouter = () => {
|
|
5
6
|
const reportRouter = new Hono();
|
|
@@ -7,5 +8,7 @@ export const createReportRouter = () => {
|
|
|
7
8
|
// 智能问数
|
|
8
9
|
reportRouter.post('/query', queryReport);
|
|
9
10
|
|
|
11
|
+
reportRouter.post('/query/suggest', queryReportSuggest);
|
|
12
|
+
|
|
10
13
|
return reportRouter;
|
|
11
14
|
};
|