feat: implement AI chat with vector search and random loading messages

Major Features:
-  AI chat with Azure OpenAI GPT-4o integration
-  Vector search across Bible versions (ASV English, RVA 1909 Spanish)
-  Multi-language support with automatic English fallback
-  Bible version citations in responses [ASV] [RVA 1909]
-  Random Bible-themed loading messages (5 variants)
-  Safe build script with memory guardrails
-  8GB swap memory for build safety
-  Stripe donation integration (multiple payment methods)

AI Chat Improvements:
- Implement vector search with 1536-dim embeddings (Azure text-embedding-ada-002)
- Search all Bible versions in user's language, fallback to English
- Cite Bible versions properly in AI responses
- Add 5 random loading messages: "Searching the Scriptures...", etc.
- Fix Ollama conflict (disabled to use Azure OpenAI exclusively)
- Optimize hybrid search queries for actual table schema

Build & Infrastructure:
- Create safe-build.sh script with memory monitoring (prevents server crashes)
- Add 8GB swap memory for emergency relief
- Document build process in BUILD_GUIDE.md
- Set Node.js memory limits (4GB max during builds)

Database:
- Clean up 115 old vector tables with wrong dimensions
- Keep only 2 tables with correct 1536-dim embeddings
- Add Stripe schema for donations and subscriptions

Documentation:
- AI_CHAT_FINAL_STATUS.md - Complete implementation status
- AI_CHAT_IMPLEMENTATION_COMPLETE.md - Technical details
- BUILD_GUIDE.md - Safe building guide with guardrails
- CHAT_LOADING_MESSAGES.md - Loading messages implementation
- STRIPE_IMPLEMENTATION_COMPLETE.md - Stripe integration docs
- STRIPE_SETUP_GUIDE.md - Stripe configuration guide

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-10-12 19:37:24 +00:00
parent b3ec31a265
commit a01377b21a
20 changed files with 3022 additions and 130 deletions

View File

@@ -47,6 +47,15 @@ import { useTranslations, useLocale } from 'next-intl'
import ReactMarkdown from 'react-markdown'
import { AuthModal } from '@/components/auth/auth-modal'
// Random Bible-related loading messages
const LOADING_MESSAGES = [
"Searching the Scriptures...",
"Seeking wisdom from God's Word...",
"Consulting the Holy Scriptures...",
"Finding relevant Bible verses...",
"Exploring God's eternal truth..."
]
interface ChatMessage {
id: string
role: 'user' | 'assistant'
@@ -84,6 +93,7 @@ export default function FloatingChat() {
])
const [inputMessage, setInputMessage] = useState('')
const [isLoading, setIsLoading] = useState(false)
const [loadingMessage, setLoadingMessage] = useState('')
// Conversation management state
const [conversations, setConversations] = useState<Conversation[]>([])
@@ -347,6 +357,10 @@ export default function FloatingChat() {
setMessages(prev => [...prev, userMessage])
setInputMessage('')
// Pick a random loading message
const randomMessage = LOADING_MESSAGES[Math.floor(Math.random() * LOADING_MESSAGES.length)]
setLoadingMessage(randomMessage)
setIsLoading(true)
try {
@@ -886,9 +900,48 @@ export default function FloatingChat() {
<SmartToy fontSize="small" />
</Avatar>
<Paper elevation={1} sx={{ p: 1.5, borderRadius: 2 }}>
<Typography variant="body2">
{t('loading')}
</Typography>
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1.5 }}>
<Box sx={{ display: 'flex', gap: 0.5 }}>
<Box sx={{
width: 8,
height: 8,
borderRadius: '50%',
bgcolor: 'primary.main',
animation: 'bounce 1.4s infinite ease-in-out both',
'@keyframes bounce': {
'0%, 80%, 100%': { transform: 'scale(0)' },
'40%': { transform: 'scale(1)' }
}
}} />
<Box sx={{
width: 8,
height: 8,
borderRadius: '50%',
bgcolor: 'primary.main',
animation: 'bounce 1.4s infinite ease-in-out both',
animationDelay: '-0.32s',
'@keyframes bounce': {
'0%, 80%, 100%': { transform: 'scale(0)' },
'40%': { transform: 'scale(1)' }
}
}} />
<Box sx={{
width: 8,
height: 8,
borderRadius: '50%',
bgcolor: 'primary.main',
animation: 'bounce 1.4s infinite ease-in-out both',
animationDelay: '-0.16s',
'@keyframes bounce': {
'0%, 80%, 100%': { transform: 'scale(0)' },
'40%': { transform: 'scale(1)' }
}
}} />
</Box>
<Typography variant="body2" sx={{ fontStyle: 'italic', color: 'text.secondary' }}>
{loadingMessage}
</Typography>
</Box>
</Paper>
</Box>
</Box>