增加总结:辩论

This commit is contained in:
IndieKKY
2024-10-09 20:17:08 +08:00
parent 69e0497081
commit 3cede8650d
5 changed files with 119 additions and 3 deletions

View File

@@ -0,0 +1,43 @@
import { useAppSelector } from '@/hooks/redux';
import React from 'react';
const DebateChat: React.FC<DebateProps> = ({ messages }) => {
const fontSize = useAppSelector(state => state.env.envData.fontSize)
return (
<div className="flex flex-col h-full">
<div className="flex-1 overflow-y-auto p-4">
{messages.map((message, index) => (
<div
key={index}
className={`flex mb-4 ${
message.side === 'pro' ? 'justify-start' : 'justify-end'
}`}
>
<div
className={`max-w-[85%] rounded-2xl p-3 shadow-md relative ${
message.side === 'pro'
? 'bg-blue-100 text-blue-800 ml-2'
: 'bg-green-100 text-green-800 mr-2'
}`}
>
<p className={`${fontSize === 'large' ? 'text-sm' : 'text-xs'} font-bold mb-1`}>
{message.side === 'pro' ? '正方' : '反方'}
</p>
<p className={fontSize === 'large' ? 'text-sm' : 'text-xs'}>{message.content}</p>
<div
className={`absolute w-4 h-4 ${
message.side === 'pro'
? 'bg-blue-100 -left-2 top-2 rounded-bl-full'
: 'bg-green-100 -right-2 top-2 rounded-br-full'
}`}
></div>
</div>
</div>
))}
</div>
</div>
);
};
export default DebateChat;

View File

@@ -2,7 +2,7 @@ import React, {MutableRefObject, useCallback, useEffect, useMemo, useRef} from '
import {useAppDispatch, useAppSelector} from '../hooks/redux'
import {setFloatKeyPointsSegIdx, setSegmentFold, setTempData} from '../redux/envReducer'
import classNames from 'classnames'
import {FaClipboardList} from 'react-icons/fa'
import {FaClipboardList, FaComments} from 'react-icons/fa'
import {PAGE_MAIN, PAGE_SETTINGS, SUMMARIZE_THRESHOLD, SUMMARIZE_TYPES} from '../consts/const'
import useTranslate from '../hooks/useTranslate'
import {BsDashSquare, BsPlusSquare, CgFileDocument, FaQuestion, GrOverview, RiFileCopy2Line} from 'react-icons/all'
@@ -12,6 +12,7 @@ import {useInViewport} from 'ahooks'
import SegmentItem from './SegmentItem'
import {stopPopFunc} from '../utils/util'
import useSubtitle from '../hooks/useSubtitle'
import DebateChat from './DebateChat'
const SummarizeItemOverview = (props: {
segment: Segment
@@ -113,6 +114,8 @@ const Summarize = (props: {
<div className={classNames('font-normal', fontSize === 'large' ? 'text-sm' : 'text-xs')}>{question.a}</div>
</div>)}
</div>}
{summary?.type === 'debate' && (summary.content != null) &&
<DebateChat messages={summary.content} />}
</div>
<div className='flex flex-col justify-center items-center'>
{segment.text.length < SUMMARIZE_THRESHOLD && <div className='desc-lighter text-xs'>.</div>}
@@ -200,6 +203,12 @@ const SegmentCard = (props: {
}))
}, [dispatch])
const onSelDebate = useCallback(() => {
dispatch(setTempData({
curSummaryType: 'debate'
}))
}, [dispatch])
return <div
className={classNames('border border-base-300 bg-base-200/25 rounded flex flex-col m-1.5 p-1.5 gap-1 shadow', showCurrent && 'shadow-primary')}>
<div className='relative flex justify-center min-h-[20px]'>
@@ -215,6 +224,7 @@ const SegmentCard = (props: {
<a className={classNames('tab tab-lifted tab-xs', curSummaryType === 'overview' && 'tab-active')} onClick={onSelOverview}><GrOverview/></a>
<a className={classNames('tab tab-lifted tab-xs', curSummaryType === 'keypoint' && 'tab-active')} onClick={onSelKeypoint}><FaClipboardList/></a>
<a className={classNames('tab tab-lifted tab-xs', curSummaryType === 'question' && 'tab-active')} onClick={onSelQuestion}><FaQuestion/></a>
<a className={classNames('tab tab-lifted tab-xs', curSummaryType === 'debate' && 'tab-active')} onClick={onSelDebate}><FaComments/></a>
<a className="tab tab-lifted tab-xs tab-disabled cursor-default"></a>
</div>}
<div

View File

@@ -11,6 +11,7 @@ export const PROMPT_TYPE_TRANSLATE = 'translate'
export const PROMPT_TYPE_SUMMARIZE_OVERVIEW = 'summarize_overview'
export const PROMPT_TYPE_SUMMARIZE_KEYPOINT = 'summarize_keypoint'
export const PROMPT_TYPE_SUMMARIZE_QUESTION = 'summarize_question'
export const PROMPT_TYPE_SUMMARIZE_DEBATE = 'summarize_debate'
export const PROMPT_TYPE_SUMMARIZE_BRIEF = 'summarize_brief'
export const PROMPT_TYPE_ASK = 'ask'
export const PROMPT_TYPES = [{
@@ -28,6 +29,9 @@ export const PROMPT_TYPES = [{
}, {
name: '问题',
type: PROMPT_TYPE_SUMMARIZE_QUESTION,
}, {
name: '辩论',
type: PROMPT_TYPE_SUMMARIZE_DEBATE,
}, {
name: '提问',
type: PROMPT_TYPE_ASK,
@@ -58,6 +62,12 @@ export const SUMMARIZE_TYPES = {
downloadName: '💡常见问题💡',
promptType: PROMPT_TYPE_SUMMARIZE_QUESTION,
},
debate: {
name: '辩论',
desc: '辩论',
downloadName: '💡辩论💡',
promptType: PROMPT_TYPE_SUMMARIZE_DEBATE,
},
}
export const PROMPT_DEFAULTS = {
@@ -175,6 +185,42 @@ Provide an example to illustrate the expected output:
}
]
\`\`\`
`,
[PROMPT_TYPE_SUMMARIZE_DEBATE]: `You are a helpful assistant skilled at generating debates based on video subtitles.
## Context
The video's title: '''{{title}}'''.
The video's subtitles:
'''
{{segment}}
'''
## Command
Please play the roles of both the affirmative and negative sides to discuss the author's viewpoint.
The conversation should consist of 10 rounds(5 sentences from the affirmative side, 5 sentences from the negative side.).
The tone should be straightforward.
Answer in language '{{language}}'.
## Output format
Provide an example to illustrate the expected output:
\`\`\`json
[
{
"side": "pro",
"content": "xxx"
},
{
"side": "con",
"content": "xxx"
}
]
\`\`\`
`,
[PROMPT_TYPE_ASK]: `You are a helpful assistant who answers question related to video subtitles.
Answer in language '{{language}}'.

11
src/typings.d.ts vendored
View File

@@ -151,4 +151,13 @@ interface BriefSummary extends Summary {
}
type SummaryStatus = 'init' | 'pending' | 'done'
type SummaryType = 'overview' | 'keypoint' | 'brief' | 'question'
type SummaryType = 'overview' | 'keypoint' | 'brief' | 'question' | 'debate'
interface DebateMessage {
side: 'pro' | 'con';
content: string;
}
interface DebateProps {
messages: DebateMessage[];
}

View File

@@ -81,6 +81,9 @@ export const isSummaryEmpty = (summary: Summary) => {
} else if (summary.type === 'question') {
const content: any[] = summary.content??[]
return content.length === 0
} else if (summary.type === 'debate') {
const content: Array<{ side: string, content: string }> = summary.content ?? []
return content.length === 0
}
return true
}
@@ -107,7 +110,12 @@ export const getSummaryStr = (summary: Summary) => {
s += content.map(item => {
return item.q + '\n' + item.a + '\n'
}).join('\n')
}
} else if (summary.type === 'debate') {
const content: Array<{ side: string, content: string }> = summary.content ?? []
s += content.map(item => {
return (item.side === 'pro'?'正方:':'反方:') + item.content + '\n'
}).join('\n')
}
return s
}