feat: storybook (#9324)

This commit is contained in:
Hash Brown
2024-10-16 10:18:48 +08:00
committed by GitHub
parent 423df67042
commit 5df1cb0566
14 changed files with 5441 additions and 502 deletions

View File

@@ -0,0 +1,61 @@
export const markdownContent = `
# Heading 1
## Heading 2
### Heading 3
#### Heading 4
##### Heading 5
###### Heading 6
# Basic markdown content.
Should support **bold**, *italic*, and ~~strikethrough~~.
Should support [links](https://www.google.com).
Should support inline \`code\` blocks.
# Number list
1. First item
2. Second item
3. Third item
# Bullet list
- First item
- Second item
- Third item
# Link
[Google](https://www.google.com)
# Image
![Alt text](https://picsum.photos/200/300)
# Table
| Column 1 | Column 2 | Column 3 |
| -------- | -------- | -------- |
| Cell 1 | Cell 2 | Cell 3 |
| Cell 4 | Cell 5 | Cell 6 |
| Cell 7 | Cell 8 | Cell 9 |
# Code
\`\`\`JavaScript
const code = "code"
\`\`\`
# Blockquote
> This is a blockquote.
# Horizontal rule
---
`

View File

@@ -0,0 +1,27 @@
export const markdownContentSVG = `
\`\`\`svg
<svg width="400" height="600" xmlns="http://www.w3.org/2000/svg">
<rect width="100%" height="100%" fill="#F0F8FF"/>
<text x="50%" y="60" font-family="楷体" font-size="32" fill="#4682B4" text-anchor="middle">创意Logo设计</text>
<line x1="50" y1="80" x2="350" y2="80" stroke="#B0C4DE" stroke-width="2"/>
<text x="50%" y="120" font-family="Arial" font-size="24" fill="#708090" text-anchor="middle">科研</text>
<text x="50%" y="150" font-family="MS Mincho" font-size="20" fill="#778899" text-anchor="middle">科学研究</text>
<text x="50%" y="200" font-family="汇文明朝体" font-size="18" fill="#696969" text-anchor="middle">
<tspan x="50%" dy="25">探索未知的灯塔,</tspan>
<tspan x="50%" dy="25">照亮人类前进的道路。</tspan>
<tspan x="50%" dy="25">科研,是永不熄灭的好奇心,</tspan>
<tspan x="50%" dy="25">也是推动世界进步的引擎。</tspan>
</text>
<circle cx="200" cy="400" r="80" fill="none" stroke="#4169E1" stroke-width="3"/>
<line x1="200" y1="320" x2="200" y2="480" stroke="#4169E1" stroke-width="3"/>
<line x1="120" y1="400" x2="280" y2="400" stroke="#4169E1" stroke-width="3"/>
<text x="50%" y="550" font-family="微软雅黑" font-size="16" fill="#1E90FF" text-anchor="middle">探索 • 创新 • 进步</text>
</svg>
\`\`\`
`

View File

@@ -0,0 +1,136 @@
import type { WorkflowProcess } from '@/app/components/base/chat/types'
import { WorkflowRunningStatus } from '@/app/components/workflow/types'
export const mockedWorkflowProcess = {
status: WorkflowRunningStatus.Succeeded,
resultText: 'Hello, how can I assist you today?',
tracing: [
{
extras: {},
id: 'f6337dc9-e280-4915-965f-10b0552dd917',
node_id: '1724232060789',
node_type: 'start',
title: 'Start',
index: 1,
predecessor_node_id: null,
inputs: {
'sys.query': 'hi',
'sys.files': [],
'sys.conversation_id': '92ce0a3e-8f15-43d1-b31d-32716c4b10a7',
'sys.user_id': 'fbff43f9-d5a4-4e85-b63b-d3a91d806c6f',
'sys.dialogue_count': 1,
'sys.app_id': 'b2e8906a-aad3-43a0-9ace-0e44cc7315e1',
'sys.workflow_id': '70004abe-561f-418b-b9e8-8c957ce55140',
'sys.workflow_run_id': '69db9267-aaee-42e1-9581-dbfb67e8eeb5',
},
process_data: null,
outputs: {
'sys.query': 'hi',
'sys.files': [],
'sys.conversation_id': '92ce0a3e-8f15-43d1-b31d-32716c4b10a7',
'sys.user_id': 'fbff43f9-d5a4-4e85-b63b-d3a91d806c6f',
'sys.dialogue_count': 1,
'sys.app_id': 'b2e8906a-aad3-43a0-9ace-0e44cc7315e1',
'sys.workflow_id': '70004abe-561f-418b-b9e8-8c957ce55140',
'sys.workflow_run_id': '69db9267-aaee-42e1-9581-dbfb67e8eeb5',
},
status: 'succeeded',
error: null,
elapsed_time: 0.035744,
execution_metadata: null,
created_at: 1728980002,
finished_at: 1728980002,
files: [],
parallel_id: null,
parallel_start_node_id: null,
parent_parallel_id: null,
parent_parallel_start_node_id: null,
iteration_id: null,
},
{
extras: {},
id: '92204d8d-4198-4c46-aa02-c2754b11dec9',
node_id: 'llm',
node_type: 'llm',
title: 'LLM',
index: 2,
predecessor_node_id: '1724232060789',
inputs: null,
process_data: {
model_mode: 'chat',
prompts: [
{
role: 'system',
text: 'hi',
files: [],
},
{
role: 'user',
text: 'hi',
files: [],
},
],
model_provider: 'openai',
model_name: 'gpt-4o-mini',
},
outputs: {
text: 'Hello! How can I assist you today?',
usage: {
prompt_tokens: 13,
prompt_unit_price: '0.15',
prompt_price_unit: '0.000001',
prompt_price: '0.0000020',
completion_tokens: 9,
completion_unit_price: '0.60',
completion_price_unit: '0.000001',
completion_price: '0.0000054',
total_tokens: 22,
total_price: '0.0000074',
currency: 'USD',
latency: 1.8902503330027685,
},
finish_reason: 'stop',
},
status: 'succeeded',
error: null,
elapsed_time: 5.089409,
execution_metadata: {
total_tokens: 22,
total_price: '0.0000074',
currency: 'USD',
},
created_at: 1728980002,
finished_at: 1728980007,
files: [],
parallel_id: null,
parallel_start_node_id: null,
parent_parallel_id: null,
parent_parallel_start_node_id: null,
iteration_id: null,
},
{
extras: {},
id: '7149bac6-60f9-4e06-a5ed-1d9d3764c06b',
node_id: 'answer',
node_type: 'answer',
title: 'Answer',
index: 3,
predecessor_node_id: 'llm',
inputs: null,
process_data: null,
outputs: {
answer: 'Hello! How can I assist you today?',
},
status: 'succeeded',
error: null,
elapsed_time: 0.015339,
execution_metadata: null,
created_at: 1728980007,
finished_at: 1728980007,
parallel_id: null,
parallel_start_node_id: null,
parent_parallel_id: null,
parent_parallel_start_node_id: null,
},
],
} as unknown as WorkflowProcess

View File

@@ -0,0 +1,96 @@
import type { Meta, StoryObj } from '@storybook/react'
import type { ChatItem } from '../../types'
import { mockedWorkflowProcess } from './__mocks__/workflowProcess'
import { markdownContent } from './__mocks__/markdownContent'
import { markdownContentSVG } from './__mocks__/markdownContentSVG'
import Answer from '.'
const meta = {
title: 'Base/Chat Answer',
component: Answer,
parameters: {
layout: 'fullscreen',
},
tags: ['autodocs'],
argTypes: {
noChatInput: { control: 'boolean', description: 'If set to true, some buttons that are supposed to be shown on hover will not be displayed.' },
responding: { control: 'boolean', description: 'Indicates if the answer is being generated.' },
showPromptLog: { control: 'boolean', description: 'If set to true, the prompt log button will be shown on hover.' },
},
args: {
noChatInput: false,
responding: false,
showPromptLog: false,
},
} satisfies Meta<typeof Answer>
export default meta
type Story = StoryObj<typeof meta>
const mockedBaseChatItem = {
id: '1',
isAnswer: true,
content: 'Hello, how can I assist you today?',
} satisfies ChatItem
export const Basic: Story = {
args: {
item: mockedBaseChatItem,
question: mockedBaseChatItem.content,
index: 0,
},
render: (args) => {
return <div className="w-full px-10 py-5">
<Answer {...args} />
</div>
},
}
export const WithWorkflowProcess: Story = {
args: {
item: {
...mockedBaseChatItem,
workflowProcess: mockedWorkflowProcess,
},
question: mockedBaseChatItem.content,
index: 0,
},
render: (args) => {
return <div className="w-full px-10 py-5">
<Answer {...args} />
</div>
},
}
export const WithMarkdownContent: Story = {
args: {
item: {
...mockedBaseChatItem,
content: markdownContent,
},
question: mockedBaseChatItem.content,
index: 0,
},
render: (args) => {
return <div className="w-full px-10 py-5">
<Answer {...args} />
</div>
},
}
export const WithMarkdownSVG: Story = {
args: {
item: {
...mockedBaseChatItem,
content: markdownContentSVG,
},
question: mockedBaseChatItem.content,
index: 0,
},
render: (args) => {
return <div className="w-full px-10 py-5">
<Answer {...args} />
</div>
},
}

View File

@@ -0,0 +1,33 @@
import type { Meta, StoryObj } from '@storybook/react'
import type { ChatItem } from '../types'
import Question from './question'
import { User } from '@/app/components/base/icons/src/public/avatar'
const meta = {
title: 'Base/Chat Question',
component: Question,
parameters: {
layout: 'centered',
},
tags: ['autodocs'],
argTypes: {},
args: {},
} satisfies Meta<typeof Question>
export default meta
type Story = StoryObj<typeof meta>
export const Default: Story = {
args: {
item: {
id: '1',
isAnswer: false,
content: 'You are a helpful assistant.',
} satisfies ChatItem,
theme: undefined,
questionIcon: <div className='w-full h-full rounded-full border-[0.5px] border-black/5'>
<User className='w-full h-full' />
</div>,
},
}