新增项目库向量化及问答模块
parent
194928e0e1
commit
ae09cf358e
|
|
@ -268,7 +268,9 @@ def _compact_cited_refs(answer: str, retrieved_docs):
|
|||
"citation_id": new_id,
|
||||
"file_path": file_path,
|
||||
"anchor_text": doc.get("anchor_text") or "",
|
||||
"excerpt": doc.get("excerpt") or doc.get("content") or doc.get("anchor_text") or "",
|
||||
# 优先使用命中文档的上下文片段(命中点前后扩展),避免分块边界
|
||||
# 的短文本(如文档末尾残余块)导致引用预览内容过少
|
||||
"excerpt": doc.get("content") or doc.get("excerpt") or doc.get("anchor_text") or "",
|
||||
})
|
||||
old_to_new[old_id] = new_id
|
||||
|
||||
|
|
|
|||
|
|
@ -410,7 +410,8 @@
|
|||
vertical-align: super;
|
||||
color: #1677ff;
|
||||
font-weight: 600;
|
||||
margin: 0 1px;
|
||||
margin: 0 3px;
|
||||
padding: 0 1px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
|
@ -578,7 +579,7 @@
|
|||
.chat-citation-preview {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
gap: 10px;
|
||||
max-width: 460px;
|
||||
}
|
||||
|
||||
|
|
@ -592,7 +593,7 @@
|
|||
overflow: auto;
|
||||
word-break: break-word;
|
||||
line-height: 1.65;
|
||||
padding: 10px;
|
||||
padding: 12px 14px;
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 8px;
|
||||
background: color-mix(in srgb, var(--border-color) 10%, transparent);
|
||||
|
|
@ -646,13 +647,11 @@
|
|||
}
|
||||
|
||||
.chat-shell .chat-composer-shell {
|
||||
margin: 0 24px 24px;
|
||||
margin: 0 24px 12px;
|
||||
}
|
||||
|
||||
.chat-new-composer {
|
||||
min-height: 150px;
|
||||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.chat-composer-input {
|
||||
|
|
@ -697,18 +696,18 @@
|
|||
}
|
||||
|
||||
.chat-composer-plus {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
min-width: 44px;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
min-width: 32px;
|
||||
border: 1px solid #f0f0f0;
|
||||
border-radius: 50%;
|
||||
background: #fff;
|
||||
box-shadow: 0 6px 18px rgba(15, 23, 42, 0.08);
|
||||
box-shadow: 0 2px 8px rgba(15, 23, 42, 0.06);
|
||||
color: var(--text-color-secondary);
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 24px;
|
||||
font-size: 16px;
|
||||
cursor: pointer;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
|
@ -778,21 +777,19 @@
|
|||
}
|
||||
|
||||
.chat-send-button {
|
||||
width: 40px !important;
|
||||
height: 40px !important;
|
||||
min-width: 40px !important;
|
||||
width: 32px !important;
|
||||
height: 32px !important;
|
||||
min-width: 32px !important;
|
||||
border: 1px solid #bebebe !important;
|
||||
background: #d1d1d1 !important;
|
||||
color: #fff !important;
|
||||
box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.28);
|
||||
font-size: 24px !important;
|
||||
font-size: 14px !important;
|
||||
line-height: 1 !important;
|
||||
transform: scale(1.08);
|
||||
transform-origin: center;
|
||||
}
|
||||
|
||||
.chat-send-button .anticon {
|
||||
font-size: 22px;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.chat-send-button:not(:disabled):hover {
|
||||
|
|
@ -885,10 +882,9 @@ body.dark .chat-search-highlight {
|
|||
}
|
||||
|
||||
.chat-send-button {
|
||||
width: 48px !important;
|
||||
height: 48px !important;
|
||||
min-width: 48px !important;
|
||||
font-size: 24px !important;
|
||||
transform: scale(1.08);
|
||||
width: 40px !important;
|
||||
height: 40px !important;
|
||||
min-width: 40px !important;
|
||||
font-size: 18px !important;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ import 'highlight.js/styles/github.css'
|
|||
import { createChatSession, deleteChatMessage, deleteChatSession, getChatMessages, getChatSessions, searchChatMessages, sendChatMessageStream, updateChatSessionTitle } from '@/api/chat'
|
||||
import { getMyProjects } from '@/api/project'
|
||||
import { getLLMModelConfigs } from '@/api/llmModelConfigs'
|
||||
import useUserStore from '@/stores/userStore'
|
||||
import './Chat.css'
|
||||
|
||||
const { TextArea } = Input
|
||||
|
|
@ -208,6 +209,7 @@ function MessageActions({ content, onCopy, onDelete }) {
|
|||
function Chat() {
|
||||
const navigate = useNavigate()
|
||||
const location = useLocation()
|
||||
const { user: currentUser } = useUserStore()
|
||||
const [searchParams, setSearchParams] = useSearchParams()
|
||||
const [sessions, setSessions] = useState([])
|
||||
const [projects, setProjects] = useState([])
|
||||
|
|
@ -232,6 +234,7 @@ function Chat() {
|
|||
const [renameSession, setRenameSession] = useState(null)
|
||||
const [renameTitle, setRenameTitle] = useState('')
|
||||
const messageRefs = useRef(new Map())
|
||||
const messagesEndRef = useRef(null)
|
||||
const skipNextOpenSessionRef = useRef(null)
|
||||
const searchRequestIdRef = useRef(0)
|
||||
const newMode = location.pathname === '/chat/new'
|
||||
|
|
@ -252,6 +255,19 @@ function Chat() {
|
|||
const canCreateSession = Boolean(newQuestion.trim() && currentProject && currentModel)
|
||||
const canSendMessage = Boolean(inputValue.trim() && currentSession)
|
||||
|
||||
// 与全站侧边栏/个人资料一致的用户头像:avatar 字段是相对路径时转换为 API 端点
|
||||
const userAvatarUrl = useMemo(() => {
|
||||
const avatar = currentUser?.avatar
|
||||
if (!avatar) return null
|
||||
if (avatar.startsWith('http')) return avatar
|
||||
const parts = avatar.split('/')
|
||||
if (parts.length >= 3) {
|
||||
return `/api/v1/auth/avatar/${parts[0]}/${parts[2]}`
|
||||
}
|
||||
return null
|
||||
}, [currentUser])
|
||||
const userDisplayName = currentUser?.nickname || currentUser?.username
|
||||
|
||||
const groupedSessions = useMemo(() => {
|
||||
const groups = []
|
||||
const groupMap = new Map()
|
||||
|
|
@ -353,6 +369,11 @@ function Chat() {
|
|||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [sessionId, sessions.length, newMode])
|
||||
|
||||
// 新会话打开或消息生成/更新时,自动滚动到对话底部
|
||||
useEffect(() => {
|
||||
messagesEndRef.current?.scrollIntoView({ behavior: 'smooth', block: 'end' })
|
||||
}, [messages, currentSession])
|
||||
|
||||
useEffect(() => {
|
||||
const target = searchParams.get('message_id')
|
||||
if (!target) return
|
||||
|
|
@ -874,11 +895,16 @@ function Chat() {
|
|||
/>
|
||||
)}
|
||||
</div>
|
||||
{isUser && <Avatar className="chat-avatar user" icon={<UserOutlined />} />}
|
||||
{isUser && (
|
||||
<Avatar className="chat-avatar user" src={userAvatarUrl} style={{ backgroundColor: '#1677ff' }}>
|
||||
{userDisplayName?.[0]?.toUpperCase() || 'U'}
|
||||
</Avatar>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
})
|
||||
)}
|
||||
<div ref={messagesEndRef} />
|
||||
</div>
|
||||
<div className="chat-composer-shell">
|
||||
<TextArea
|
||||
|
|
|
|||
Loading…
Reference in New Issue