Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Q
qianjiangb2b
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
AI-甘富林
qianjiangb2b
Commits
abf55760
Commit
abf55760
authored
Jun 17, 2026
by
AI-甘富林
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ai对话记忆修复,表格展示
parent
f5554d02
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
97 additions
and
2 deletions
+97
-2
index.ts
supabase/functions/coze-langchain/index.ts
+97
-2
No files found.
supabase/functions/coze-langchain/index.ts
View file @
abf55760
...
@@ -363,6 +363,7 @@ interface GenUIResponse {
...
@@ -363,6 +363,7 @@ interface GenUIResponse {
gap?: string;
gap?: string;
components: any[];
components: any[];
};
};
ui_schema_text?: string;
suggested_actions?: string[];
suggested_actions?: string[];
}
}
...
@@ -370,8 +371,97 @@ interface GenUIResponse {
...
@@ -370,8 +371,97 @@ interface GenUIResponse {
// 统一 AI 大模型调用(通过 _shared/aiProvider)
// 统一 AI 大模型调用(通过 _shared/aiProvider)
// ========================
// ========================
/** 将 ui_schema 组件转为可存储、可展示的 Markdown 文本 */
function uiSchemaToMarkdown(uiSchema: any): string {
if (!uiSchema?.components || !Array.isArray(uiSchema.components)) return "";
const parts: string[] = [];
for (const comp of uiSchema.components) {
const props = comp.props || {};
switch (comp.type) {
case 'data_table': {
const { title, columns, rows } = props;
if (!columns || !rows) break;
let table = '';
if (title) table += `
**
$
{
title
}
**
\
n
\
n
`;
// 表头
table += '| ' + columns.map((c: any) => c.label || c.key).join(' | ') + ' |\n';
table += '| ' + columns.map(() => '---').join(' | ') + ' |\n';
// 数据行
for (const row of rows) {
table += '| ' + columns.map((c: any) => row[c.key] != null ? String(row[c.key]) : '').join(' | ') + ' |\n';
}
parts.push(table);
break;
}
case 'stats_row': {
const { items } = props;
if (!items || !Array.isArray(items)) break;
const statsText = items.map((item: any) =>
`
-
**
$
{
item
.
label
}
**
:
$
{
item
.
value
}
`
).
join
(
'
\
n'
);
parts
.
push
(
statsText
);
break
;
}
case
'insight_feed'
:
{
const
{
title
,
insights
}
=
props
;
if
(
title
)
parts
.
push
(
`**
${
title
}
**`
);
if
(
insights
&&
Array
.
isArray
(
insights
))
{
for
(
const
ins
of
insights
)
{
const
emoji
=
ins
.
type
===
'warning'
?
'⚠️'
:
ins
.
type
===
'success'
?
'✅'
:
ins
.
type
===
'error'
?
'❌'
:
'ℹ️'
;
parts
.
push
(
`-
${
emoji
}
**
${
ins
.
title
}
**:
${
ins
.
description
||
''
}
`
);
}
}
break
;
}
case
'alert'
:
{
const
alertEmoji
=
props
.
type
===
'error'
?
'❌'
:
props
.
type
===
'warning'
?
'⚠️'
:
props
.
type
===
'success'
?
'✅'
:
'ℹ️'
;
parts
.
push
(
`>
${
alertEmoji
}
**
${
props
.
title
||
''
}
**\n>
${
props
.
description
||
''
}
`
);
break
;
}
case
'chart'
:
{
const
{
title
,
data
}
=
props
;
if
(
title
)
parts
.
push
(
`**
${
title
}
**`
);
if
(
data
&&
Array
.
isArray
(
data
))
{
for
(
const
d
of
data
)
{
parts
.
push
(
`-
${
d
.
label
}
:
${
d
.
value
}
`
);
}
}
break
;
}
case
'text'
:
{
parts
.
push
(
props
.
content
||
''
);
break
;
}
case
'progress_bar'
:
{
const
pct
=
props
.
target
?
Math
.
round
((
props
.
current
/
props
.
target
)
*
100
)
:
0
;
parts
.
push
(
`- **
${
props
.
label
}
**:
${
props
.
current
}
/
${
props
.
target
}
(
${
pct
}
%)`
);
break
;
}
case
'approval_list'
:
{
const
{
title
,
approvals
}
=
props
;
if
(
title
)
parts
.
push
(
`**
${
title
}
**`
);
if
(
approvals
&&
Array
.
isArray
(
approvals
))
{
for
(
const
a
of
approvals
)
{
const
prio
=
a
.
priority
===
'high'
?
'🔴'
:
a
.
priority
===
'medium'
?
'🟡'
:
'🟢'
;
parts
.
push
(
`-
${
prio
}
**
${
a
.
title
}
** —
${
a
.
description
||
''
}
(发起人:
${
a
.
agent
||
'-'
}
)`
);
}
}
break
;
}
}
}
return
parts
.
join
(
'
\
n
\
n'
);
}
/**
/**
* 将 AI 返回的原始文本解析为 GenUIResponse
* 将 AI 返回的原始文本解析为 GenUIResponse
* - 提取 ```json 前的纯文本作为 textAnswer
* - 解析 JSON 中的 ui_schema
* - 将 ui_schema 组件转为 Markdown 追加到 answer,确保存储和展示都有完整数据
*/
*/
function
parseAIResponse
(
raw
:
string
):
GenUIResponse
{
function
parseAIResponse
(
raw
:
string
):
GenUIResponse
{
let
jsonContent
=
raw
.
trim
();
let
jsonContent
=
raw
.
trim
();
...
@@ -417,12 +507,16 @@ function parseAIResponse(raw: string): GenUIResponse {
...
@@ -417,12 +507,16 @@ function parseAIResponse(raw: string): GenUIResponse {
});
});
}
}
console
.
log
(
`[CozeLangchain] AI JSON parsed, has ui_schema:
${
!!
uiSchema
}
`
);
// 将 ui_schema 组件转为 Markdown 文本,供前端存库用(历史消息可读)
const
uiSchemaText
=
uiSchemaToMarkdown
(
uiSchema
);
console
.
log
(
`[CozeLangchain] AI JSON parsed, has ui_schema:
${
!!
uiSchema
}
, uiSchemaText length:
${
uiSchemaText
.
length
}
`
);
return
{
return
{
//
优先用新格式的纯文本回答,其次用 JSON 内的 answer 字段
//
answer 保持干净:纯文本回答,不混入组件数据
answer
:
textAnswer
||
parsed
.
answer
||
"已为您生成界面"
,
answer
:
textAnswer
||
parsed
.
answer
||
"已为您生成界面"
,
ui_schema
:
uiSchema
,
ui_schema
:
uiSchema
,
ui_schema_text
:
uiSchemaText
||
undefined
,
// 单独字段,前端拼接存库
suggested_actions
:
parsed
.
suggested_actions
,
suggested_actions
:
parsed
.
suggested_actions
,
};
};
}
catch
{
}
catch
{
...
@@ -714,6 +808,7 @@ ${dataContext}
...
@@ -714,6 +808,7 @@ ${dataContext}
type
:
"done"
,
type
:
"done"
,
answer
:
genUIResult
.
answer
,
answer
:
genUIResult
.
answer
,
ui_schema
:
genUIResult
.
ui_schema
,
ui_schema
:
genUIResult
.
ui_schema
,
ui_schema_text
:
genUIResult
.
ui_schema_text
,
suggested_actions
:
genUIResult
.
suggested_actions
,
suggested_actions
:
genUIResult
.
suggested_actions
,
agent_type
:
agentType
,
agent_type
:
agentType
,
session_id
:
sessionId
,
session_id
:
sessionId
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment