Files
users/services/intelligent-search-service.ts
v0 4eed69520c feat: refactor data asset center for enhanced search and analytics
Refactor homepage for focused search and data display; streamline data platform; enhance user and tag management; focus AI assistant on data analysis and report generation.

Co-authored-by: null <4804959+fnvtk@users.noreply.github.com>
2025-07-25 06:42:34 +00:00

474 lines
14 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 智能搜索服务 - 实现亚秒级查询和AI增强搜索
import { getMindsDBConnector, type SearchRequest, type AIQueryRequest } from "@/lib/mindsdb-connector"
export interface SearchResult {
id: string
type: "user" | "traffic" | "insight"
title: string
description: string
tags: string[]
relevanceScore: number
updatedAt: string
metadata?: Record<string, any>
}
export interface SearchStats {
totalResults: number
queryTime: number
suggestions: string[]
filters: Record<string, any>
}
export interface SearchResponse {
results: SearchResult[]
stats: SearchStats
hasMore: boolean
}
export class IntelligentSearchService {
private mindsDB = getMindsDBConnector()
private searchHistory: string[] = []
private popularQueries: Map<string, number> = new Map()
// 智能搜索主入口
async search(
query: string,
type: "user" | "traffic" | "all" = "all",
options: {
limit?: number
offset?: number
filters?: Record<string, any>
useAI?: boolean
includeInsights?: boolean
} = {},
): Promise<SearchResponse> {
const startTime = Date.now()
try {
// 记录搜索历史
this.addToSearchHistory(query)
// 如果启用AI增强搜索
if (options.useAI) {
return await this.aiEnhancedSearch(query, type, options)
}
// 标准搜索
const searchRequest: SearchRequest = {
keyword: query,
type,
filters: options.filters,
limit: options.limit || 50,
offset: options.offset || 0,
}
const rawResults = await this.mindsDB.intelligentSearch(searchRequest)
const results = this.formatSearchResults(rawResults)
// 如果需要包含AI洞察
if (options.includeInsights) {
const insights = await this.generateSearchInsights(query, results)
results.push(...insights)
}
const queryTime = Date.now() - startTime
return {
results,
stats: {
totalResults: results.length,
queryTime,
suggestions: await this.generateSuggestions(query),
filters: this.extractAvailableFilters(results),
},
hasMore: results.length === (options.limit || 50),
}
} catch (error) {
console.error("搜索失败:", error)
throw error
}
}
// AI增强搜索
private async aiEnhancedSearch(
query: string,
type: "user" | "traffic" | "all",
options: any,
): Promise<SearchResponse> {
const startTime = Date.now()
// 使用AI理解查询意图
const aiRequest: AIQueryRequest = {
query: `分析这个搜索查询的意图并提供相关的搜索建议: "${query}"`,
model: "gpt4",
useCache: true,
}
const aiAnalysis = await this.mindsDB.aiQuery(aiRequest)
// 基于AI分析结果优化搜索参数
const enhancedSearchRequest: SearchRequest = {
keyword: query,
type,
filters: {
...options.filters,
...this.extractFiltersFromAI(aiAnalysis),
},
limit: options.limit || 50,
offset: options.offset || 0,
}
const rawResults = await this.mindsDB.intelligentSearch(enhancedSearchRequest)
const results = this.formatSearchResults(rawResults)
// AI生成的相关洞察
const aiInsights = await this.generateAIInsights(query, results)
results.push(...aiInsights)
const queryTime = Date.now() - startTime
return {
results,
stats: {
totalResults: results.length,
queryTime,
suggestions: await this.generateAISuggestions(query, aiAnalysis),
filters: this.extractAvailableFilters(results),
},
hasMore: results.length === (options.limit || 50),
}
}
// 格式化搜索结果
private formatSearchResults(rawResults: any[]): SearchResult[] {
return rawResults.map((result) => ({
id: result.id || result.user_id || result.keyword_id,
type: result.type || "user",
title: result.title || result.username || result.keyword,
description: result.description || this.generateDescription(result),
tags: this.parseTags(result.tags),
relevanceScore: result.relevance_score || 0,
updatedAt: result.updated_at || result.last_active || result.last_updated,
metadata: {
...result,
searchType: result.type,
},
}))
}
// 生成描述
private generateDescription(result: any): string {
if (result.type === "user") {
return `${result.phone || ""} | ${result.email || ""} | RFM: ${result.rfm_score || "N/A"}`
} else if (result.type === "traffic") {
return `搜索量: ${result.search_volume || "N/A"} | 竞争度: ${result.competition || "N/A"} | CPC: ${result.cpc || "N/A"}`
}
return result.description || ""
}
// 解析标签
private parseTags(tags: any): string[] {
if (typeof tags === "string") {
try {
return JSON.parse(tags)
} catch {
return tags.split(",").map((tag) => tag.trim())
}
}
return Array.isArray(tags) ? tags : []
}
// 生成搜索建议
private async generateSuggestions(query: string): Promise<string[]> {
const suggestions: string[] = []
// 基于搜索历史的建议
const historySuggestions = this.searchHistory
.filter((h) => h.toLowerCase().includes(query.toLowerCase()) && h !== query)
.slice(0, 3)
suggestions.push(...historySuggestions)
// 基于热门查询的建议
const popularSuggestions = Array.from(this.popularQueries.entries())
.sort((a, b) => b[1] - a[1])
.map(([q]) => q)
.filter((q) => q.toLowerCase().includes(query.toLowerCase()) && q !== query)
.slice(0, 3)
suggestions.push(...popularSuggestions)
// 智能补全建议
const completionSuggestions = await this.generateCompletionSuggestions(query)
suggestions.push(...completionSuggestions)
return [...new Set(suggestions)].slice(0, 8)
}
// 生成AI建议
private async generateAISuggestions(query: string, aiAnalysis: any): Promise<string[]> {
try {
const aiRequest: AIQueryRequest = {
query: `基于查询"${query}"和分析结果生成5个相关的搜索建议`,
model: "gpt4",
useCache: true,
}
const result = await this.mindsDB.aiQuery(aiRequest)
return this.parseAISuggestions(result)
} catch (error) {
console.error("生成AI建议失败:", error)
return []
}
}
// 生成补全建议
private async generateCompletionSuggestions(query: string): Promise<string[]> {
// 这里可以集成更复杂的自动补全逻辑
const commonSuffixes = ["分析", "统计", "趋势", "预测", "报告", "用户", "流量", "关键词", "转化", "留存"]
return commonSuffixes
.map((suffix) => `${query} ${suffix}`)
.filter((suggestion) => suggestion.length <= 50)
.slice(0, 3)
}
// 解析AI建议
private parseAISuggestions(aiResult: any): string[] {
try {
// 假设AI返回的是建议列表
if (aiResult.suggestions && Array.isArray(aiResult.suggestions)) {
return aiResult.suggestions
}
// 如果是文本格式,尝试解析
if (typeof aiResult === "string") {
const lines = aiResult.split("\n")
return lines
.filter((line) => line.trim().length > 0)
.map((line) => line.replace(/^\d+\.\s*/, "").trim())
.slice(0, 5)
}
return []
} catch (error) {
console.error("解析AI建议失败:", error)
return []
}
}
// 从AI分析中提取过滤器
private extractFiltersFromAI(aiAnalysis: any): Record<string, any> {
const filters: Record<string, any> = {}
try {
if (aiAnalysis.filters) {
Object.assign(filters, aiAnalysis.filters)
}
// 基于AI分析结果添加智能过滤器
if (aiAnalysis.intent === "high_value_users") {
filters.rfm_score = { $gte: 80 }
}
if (aiAnalysis.intent === "recent_activity") {
filters.last_active = { $gte: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000) }
}
} catch (error) {
console.error("提取AI过滤器失败:", error)
}
return filters
}
// 生成搜索洞察
private async generateSearchInsights(query: string, results: SearchResult[]): Promise<SearchResult[]> {
const insights: SearchResult[] = []
try {
// 用户相关洞察
const userResults = results.filter((r) => r.type === "user")
if (userResults.length > 0) {
const userInsight = await this.generateUserInsight(query, userResults)
if (userInsight) insights.push(userInsight)
}
// 流量相关洞察
const trafficResults = results.filter((r) => r.type === "traffic")
if (trafficResults.length > 0) {
const trafficInsight = await this.generateTrafficInsight(query, trafficResults)
if (trafficInsight) insights.push(trafficInsight)
}
} catch (error) {
console.error("生成搜索洞察失败:", error)
}
return insights
}
// 生成AI洞察
private async generateAIInsights(query: string, results: SearchResult[]): Promise<SearchResult[]> {
const insights: SearchResult[] = []
try {
const aiRequest: AIQueryRequest = {
query: `基于搜索查询"${query}"和${results.length}个结果生成3个关键业务洞察`,
model: "gpt4",
useCache: true,
}
const aiResult = await this.mindsDB.aiQuery(aiRequest)
const aiInsights = this.parseAIInsights(aiResult)
insights.push(...aiInsights)
} catch (error) {
console.error("生成AI洞察失败:", error)
}
return insights
}
// 解析AI洞察
private parseAIInsights(aiResult: any): SearchResult[] {
const insights: SearchResult[] = []
try {
if (aiResult.insights && Array.isArray(aiResult.insights)) {
aiResult.insights.forEach((insight: any, index: number) => {
insights.push({
id: `ai_insight_${Date.now()}_${index}`,
type: "insight",
title: insight.title || `AI洞察 ${index + 1}`,
description: insight.description || insight.content,
tags: ["AI洞察", "智能分析"],
relevanceScore: insight.confidence || 0.8,
updatedAt: new Date().toISOString(),
metadata: {
source: "ai",
confidence: insight.confidence,
type: "insight",
},
})
})
}
} catch (error) {
console.error("解析AI洞察失败:", error)
}
return insights
}
// 生成用户洞察
private async generateUserInsight(query: string, userResults: SearchResult[]): Promise<SearchResult | null> {
try {
const totalUsers = userResults.length
const avgRelevance = userResults.reduce((sum, r) => sum + r.relevanceScore, 0) / totalUsers
return {
id: `user_insight_${Date.now()}`,
type: "insight",
title: "用户搜索洞察",
description: `找到 ${totalUsers} 个相关用户,平均相关度 ${avgRelevance.toFixed(2)}`,
tags: ["用户分析", "搜索洞察"],
relevanceScore: 0.9,
updatedAt: new Date().toISOString(),
metadata: {
totalUsers,
avgRelevance,
type: "user_insight",
},
}
} catch (error) {
console.error("生成用户洞察失败:", error)
return null
}
}
// 生成流量洞察
private async generateTrafficInsight(query: string, trafficResults: SearchResult[]): Promise<SearchResult | null> {
try {
const totalKeywords = trafficResults.length
const avgRelevance = trafficResults.reduce((sum, r) => sum + r.relevanceScore, 0) / totalKeywords
return {
id: `traffic_insight_${Date.now()}`,
type: "insight",
title: "流量关键词洞察",
description: `找到 ${totalKeywords} 个相关关键词,平均相关度 ${avgRelevance.toFixed(2)}`,
tags: ["流量分析", "关键词洞察"],
relevanceScore: 0.9,
updatedAt: new Date().toISOString(),
metadata: {
totalKeywords,
avgRelevance,
type: "traffic_insight",
},
}
} catch (error) {
console.error("生成流量洞察失败:", error)
return null
}
}
// 提取可用过滤器
private extractAvailableFilters(results: SearchResult[]): Record<string, any> {
const filters: Record<string, any> = {}
// 提取类型过滤器
const types = [...new Set(results.map((r) => r.type))]
if (types.length > 1) {
filters.type = types
}
// 提取标签过滤器
const allTags = results.flatMap((r) => r.tags)
const uniqueTags = [...new Set(allTags)]
if (uniqueTags.length > 0) {
filters.tags = uniqueTags.slice(0, 20) // 限制标签数量
}
return filters
}
// 添加到搜索历史
private addToSearchHistory(query: string): void {
if (query.trim().length === 0) return
// 更新搜索历史
this.searchHistory.unshift(query)
this.searchHistory = [...new Set(this.searchHistory)].slice(0, 100) // 保留最近100个唯一查询
// 更新热门查询统计
const count = this.popularQueries.get(query) || 0
this.popularQueries.set(query, count + 1)
}
// 获取搜索统计
getSearchStats(): any {
return {
totalSearches: this.searchHistory.length,
uniqueQueries: new Set(this.searchHistory).size,
popularQueries: Array.from(this.popularQueries.entries())
.sort((a, b) => b[1] - a[1])
.slice(0, 10)
.map(([query, count]) => ({ query, count })),
}
}
// 清理搜索历史
clearSearchHistory(): void {
this.searchHistory = []
this.popularQueries.clear()
}
}
// 单例模式
let searchServiceInstance: IntelligentSearchService | null = null
export function getIntelligentSearchService(): IntelligentSearchService {
if (!searchServiceInstance) {
searchServiceInstance = new IntelligentSearchService()
}
return searchServiceInstance
}