prompt-optimizer搜索功能:全文搜索与过滤机制实现
还在为海量提示词模板难以快速定位而烦恼吗?prompt-optimizer的智能搜索系统帮你一键解决!本文将深入解析prompt-optimizer的全文搜索与过滤机制实现,让你彻底掌握高效模板管理技巧。
读完本文,你将获得:
- 模板搜索架构的完整理解
- 多维度过滤机制的技术实现
- 性能优化与用户体验的最佳实践
- 自定义搜索扩展的开发指南
搜索系统架构设计
prompt-optimizer采用分层搜索架构,确保高效性和扩展性:
核心搜索接口设计
系统通过ITemplateManager
接口提供统一的搜索能力:
interface ITemplateManager {
// 基础模板管理
getTemplate(id: string): Promise<Template>
saveTemplate(template: Template): Promise<void>
deleteTemplate(id: string): Promise<void>
// 搜索与过滤功能
listTemplates(): Promise<Template[]>
listTemplatesByType(type: 'optimize' | 'userOptimize' | 'iterate'): Promise<Template[]>
// 高级搜索方法
searchTemplates(query: string, filters?: SearchFilters): Promise<Template[]>
filterTemplatesByCriteria(criteria: TemplateCriteria): Promise<Template[]>
}
interface SearchFilters {
type?: TemplateType
isBuiltin?: boolean
language?: string
minLastModified?: number
maxLastModified?: number
}
interface TemplateCriteria {
keywords?: string[]
contentContains?: string
nameContains?: string
descriptionContains?: string
}
全文搜索实现机制
关键词匹配算法
系统采用多字段加权匹配算法,确保搜索结果的相关性:
class TemplateSearchEngine {
private async searchTemplates(
query: string,
templates: Template[]
): Promise<Template[]> {
const keywords = this.extractKeywords(query);
const scoredTemplates = templates.map(template => ({
template,
score: this.calculateRelevanceScore(template, keywords)
}));
return scoredTemplates
.filter(item => item.score > 0)
.sort((a, b) => b.score - a.score)
.map(item => item.template);
}
private calculateRelevanceScore(
template: Template,
keywords: string[]
): number {
let score = 0;
// 名称匹配权重最高
score += this.matchKeywords(template.name, keywords) * 3;
// 描述匹配权重中等
score += this.matchKeywords(template.metadata.description, keywords) * 2;
// 内容匹配权重较低但范围更广
score += this.matchKeywords(template.content, keywords) * 1;
// 元数据字段匹配
if (template.metadata.author) {
score += this.matchKeywords(template.metadata.author, keywords) * 1.5;
}
return score;
}
private matchKeywords(text: string, keywords: string[]): number {
if (!text) return 0;
const lowerText = text.toLowerCase();
return keywords.reduce((score, keyword) => {
const lowerKeyword = keyword.toLowerCase();
if (lowerText.includes(lowerKeyword)) {
// 完全匹配得分更高
const exactMatch = lowerText === lowerKeyword ? 2 : 1;
// 位置权重:开头匹配得分更高
const positionBonus = lowerText.startsWith(lowerKeyword) ? 1.5 : 1;
return score + exactMatch * positionBonus;
}
return score;
}, 0);
}
}
实时搜索优化
为实现流畅的实时搜索体验,系统采用以下优化策略:
class SearchOptimizer {
private searchDebounceTimer: NodeJS.Timeout | null = null;
private searchCache = new Map<string, Template[]>();
async debouncedSearch(
query: string,
callback: (results: Template[]) => void
): Promise<void> {
// 清除之前的定时器
if (this.searchDebounceTimer) {
clearTimeout(this.searchDebounceTimer);
}
// 空查询直接返回所有模板
if (!query.trim()) {
callback(await this.getAllTemplates());
return;
}
// 检查缓存
const cacheKey = this.generateCacheKey(query);
if (this.searchCache.has(cacheKey)) {
callback(this.searchCache.get(cacheKey)!);
return;
}
// 设置防抖延迟
this.searchDebounceTimer = setTimeout(async () => {
try {
const results = await this.performSearch(query);
this.searchCache.set(cacheKey, results);
callback(results);
} catch (error) {
console.error('Search failed:', error);
callback([]);
}
}, 300); // 300ms防抖延迟
}
private generateCacheKey(query: string): string {
return query.toLowerCase().trim();
}
}
多维度过滤系统
模板类型过滤
系统支持按模板类型进行精确过滤:
class TemplateFilter {
async filterByType(
templates: Template[],
type: TemplateType
): Promise<Template[]> {
return templates.filter(template =>
template.metadata.templateType === type
);
}
async filterByBuiltinStatus(
templates: Template[],
isBuiltin: boolean
): Promise<Template[]> {
return templates.filter(template =>
template.isBuiltin === isBuiltin
);
}
async filterByMultipleCriteria(
templates: Template[],
criteria: FilterCriteria
): Promise<Template[]> {
return templates.filter(template => {
// 类型过滤
if (criteria.type && template.metadata.templateType !== criteria.type) {
return false;
}
// 内置状态过滤
if (criteria.isBuiltin !== undefined &&
template.isBuiltin !== criteria.isBuiltin) {
return false;
}
// 时间范围过滤
if (criteria.minLastModified &&
template.metadata.lastModified < criteria.minLastModified) {
return false;
}
if (criteria.maxLastModified &&
template.metadata.lastModified > criteria.maxLastModified) {
return false;
}
// 语言过滤
if (criteria.language &&
template.metadata.language !== criteria.language) {
return false;
}
return true;
});
}
}
复合过滤工作流
系统支持复杂的多条件组合过滤:
用户界面集成
搜索组件实现
前端采用Vue 3组合式API实现响应式搜索组件:
<template>
<div class="search-container">
<!-- 搜索输入框 -->
<div class="search-input-group">
<input
v-model="searchQuery"
:placeholder="t('templateManager.searchPlaceholder')"
class="search-input"
@input="handleSearchInput"
/>
<div class="search-icon">
<svg><!-- 搜索图标 --></svg>
</div>
</div>
<!-- 过滤选项 -->
<div class="filter-options">
<select v-model="selectedType" @change="applyFilters">
<option value="">所有类型</option>
<option value="optimize">优化模板</option>
<option value="userOptimize">用户优化模板</option>
<option value="iterate">迭代模板</option>
</select>
<label class="filter-checkbox">
<input
type="checkbox"
v-model="showBuiltinOnly"
@change="applyFilters"
/>
仅显示内置模板
</label>
</div>
<!-- 搜索结果 -->
<div class="search-results">
<div
v-for="template in filteredTemplates"
:key="template.id"
class="template-card"
@click="selectTemplate(template)"
>
<h4>{{ template.name }}</h4>
<p class="description">{{ template.metadata.description }}</p>
<div class="template-meta">
<span :class="['badge', template.isBuiltin ? 'builtin' : 'custom']">
{{ template.isBuiltin ? '内置' : '自定义' }}
</span>
<span class="type-badge">{{ template.metadata.templateType }}</span>
</div>
</div>
<div v-if="filteredTemplates.length === 0" class="no-results">
未找到匹配的模板
</div>
</div>
</div>
</template>
<script setup>
import { ref, computed, watch } from 'vue'
import { useTemplateManager } from '../composables/useTemplateManager'
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
const props = defineProps({
templates: {
type: Array,
required: true
}
})
const searchQuery = ref('')
const selectedType = ref('')
const showBuiltinOnly = ref(false)
const searchResults = ref([])
// 防抖搜索处理
let searchTimeout = null
const handleSearchInput = () => {
clearTimeout(searchTimeout)
searchTimeout = setTimeout(() => {
performSearch()
}, 300)
}
// 执行搜索
const performSearch = async () => {
if (!searchQuery.value.trim()) {
searchResults.value = props.templates
return
}
try {
// 调用模板管理器的搜索功能
const results = await templateManager.searchTemplates(
searchQuery.value,
{
type: selectedType.value || undefined,
isBuiltin: showBuiltinOnly.value ? true : undefined
}
)
searchResults.value = results
} catch (error) {
console.error('Search failed:', error)
searchResults.value = []
}
}
// 应用过滤条件
const applyFilters = () => {
performSearch()
}
// 计算最终显示的模板列表
const filteredTemplates = computed(() => {
let results = searchResults.value
// 应用类型过滤
if (selectedType.value) {
results = results.filter(t =>
t.metadata.templateType === selectedType.value
)
}
// 应用内置状态过滤
if (showBuiltinOnly.value) {
results = results.filter(t => t.isBuiltin)
}
return results
})
// 监听模板数据变化
watch(() => props.templates, (newTemplates) => {
searchResults.value = newTemplates
performSearch()
})
// 初始化
searchResults.value = props.templates
</script>
性能优化策略
为确保搜索体验的流畅性,系统实施多项优化措施:
优化策略 | 实现方式 | 效果提升 |
---|---|---|
防抖处理 | 300ms延迟执行搜索 | 减少不必要的搜索请求 |
结果缓存 | 基于查询关键词的缓存 | 重复搜索即时响应 |
懒加载 | 虚拟滚动和分页加载 | 处理大量数据时保持流畅 |
索引优化 | 预处理模板元数据 | 加速匹配计算 |
class SearchPerformanceOptimizer {
private precomputedIndex: Map<string, Template[]> = new Map();
async buildSearchIndex(templates: Template[]): Promise<void> {
// 预处理名称索引
templates.forEach(template => {
this.addToIndex(template.name, template);
this.addToIndex(template.metadata.description, template);
// 分词处理
const words = this.tokenizeText(template.name + ' ' + template.metadata.description);
words.forEach(word => this.addToIndex(word, template));
});
}
private addToIndex(text: string, template: Template): void {
if (!text) return;
const key = text.toLowerCase().trim();
if (!this.precomputedIndex.has(key)) {
this.precomputedIndex.set(key, []);
}
this.precomputedIndex.get(key)!.push(template);
}
private tokenizeText(text: string): string[] {
return text
.toLowerCase()
.split(/[\s\p{P}]+/u)
.filter(word => word.length > 2); // 过滤短词
}
async fastSearch(query: string): Promise<Template[]> {
const keywords = this.tokenizeText(query);
const results = new Map<string, Template>();
keywords.forEach(keyword => {
const matches = this.precomputedIndex.get(keyword) || [];
matches.forEach(template => {
results.set(template.id, template);
});
});
return Array.from(results.values());
}
}
高级搜索特性
模糊搜索支持
系统支持模糊匹配,提高搜索容错能力:
class FuzzySearch {
private static similarity(a: string, b: string): number {
const longer = a.length > b.length ? a : b;
const shorter = a.length > b.length ? b : a;
if (longer.length === 0) return 1.0;
return (longer.length - this.editDistance(longer, shorter)) / longer.length;
}
private static editDistance(s1: string, s2: string): number {
s1 = s1.toLowerCase();
s2 = s2.toLowerCase();
const costs: number[] = [];
for (let i = 0; i <= s1.length; i++) {
let lastValue = i;
for (let j = 0; j <= s2.length; j++) {
if (i === 0) {
costs[j] = j;
} else {
if (j > 0) {
let newValue = costs[j - 1];
if (s1.charAt(i - 1) !== s2.charAt(j - 1)) {
newValue = Math.min(Math.min(newValue, lastValue), costs[j]) + 1;
}
costs[j - 1] = lastValue;
lastValue = newValue;
}
}
}
if (i > 0) costs[s2.length] = lastValue;
}
return costs[s2.length];
}
static fuzzyMatch(text: string, search: string, threshold = 0.6): boolean {
return this.similarity(text, search) > threshold;
}
}
搜索语法解析
支持高级搜索语法,提升搜索精度:
class SearchQueryParser {
parse(query: string): ParsedQuery {
const result: ParsedQuery = {
keywords: [],
filters: {},
exactPhrases: []
};
// 解析引号内的精确短语
const phraseRegex = /"([^"]+)"/g;
let match;
while ((match = phraseRegex.exec(query)) !== null) {
result.exactPhrases.push(match[1]);
query = query.replace(match[0], '');
}
// 解析过滤器
const filterRegex = /(type|isBuiltin|language):(\w+)/g;
while ((match = filterRegex.exec(query)) !== null) {
const [_, key, value] = match;
result.filters[key as keyof SearchFilters] = value;
query = query.replace(match[0], '');
}
// 剩余部分作为关键词
result.keywords = query
.trim()
.split(/\s+/)
.filter(word => word.length > 0);
return result;
}
}
测试与质量保证
搜索功能测试用例
确保搜索功能的可靠性和准确性:
describe('Template Search Functionality', () => {
let templateManager: TemplateManager;
let testTemplates: Template[];
beforeEach(async () => {
templateManager = createTestTemplateManager();
testTemplates = await createTestTemplates();
});
test('should return all templates when search query is empty', async () => {
const results = await templateManager.searchTemplates('');
expect(results).toHaveLength(testTemplates.length);
});
test('should filter by template type', async () => {
const results = await templateManager.searchTemplates('', {
type: 'optimize'
});
results.forEach(template => {
expect(template.metadata.templateType).toBe('optimize');
});
});
test('should find templates by name keyword', async () => {
const results = await templateManager.searchTemplates('翻译');
const hasMatchingName = results.some(t =>
t.name.toLowerCase().includes('翻译')
);
expect(hasMatchingName).toBe(true);
});
test('should support fuzzy matching for typos', async () => {
const results = await templateManager.searchTemplates('翻译模板');
const exactResults = await templateManager.searchTemplates('翻译模板');
// 模糊搜索应该返回相似的结果
expect(results.length).toBeGreaterThan(0);
expect(results).toEqual(exactResults);
});
test('should handle complex filter combinations', async () => {
const results = await templateManager.searchTemplates('优化', {
type: 'optimize',
isBuiltin: true,
language: 'zh-CN'
});
results.forEach(template => {
expect(template.metadata.templateType).toBe('optimize');
expect(template.isBuiltin).toBe(true);
expect(template.metadata.language).toBe('zh-CN');
});
});
});
性能基准测试
确保搜索性能满足用户体验要求:
describe('Search Performance Benchmarks', () => {
const LARGE_TEMPLATE_SET = generateLargeTemplateSet(1000);
test('should handle large template sets within acceptable time', async () => {
const startTime = performance.now();
const results = await templateManager.searchTemplates(
'test query',
{},
LARGE_TEMPLATE_SET
);
const endTime = performance.now();
const duration = endTime - startTime;
// 确保搜索在100ms内完成
expect(duration).toBeLessThan(100);
expect(results).toBeInstanceOf(Array);
});
test('should scale linearly with template count', async () => {
const sizes = [100, 500, 1000];
const durations: number[] = [];
for (const size of sizes) {
const templates = generateLargeTemplateSet(size);
const startTime = performance.now();
await templateManager.searchTemplates('query', {}, templates);
durations.push(performance.now() - startTime);
}
// 验证性能增长是线性的而非指数级
const growthRate = durations[2] / durations[0];
expect(growthRate).toBeLessThan(10); // 1000个模板比100个模板慢不超过10倍
});
});
总结与最佳实践
prompt-optimizer的搜索系统通过精心设计的架构和优化策略,提供了高效、准确的模板搜索体验。关键实践包括:
- 分层架构设计:分离搜索逻辑与界面渲染,确保可维护性
- 智能匹配算法:多字段加权评分,提升结果相关性
- 性能优化:防抖、缓存、索引预处理等策略确保流畅体验
- 扩展性考虑:支持自定义过滤器和搜索语法
通过本文的深入解析,你应该能够充分理解prompt-optimizer搜索功能的实现原理,并能够根据实际需求进行定制扩展。无论是处理海量模板数据还是实现复杂的搜索需求,这套系统都提供了可靠的技术基础。
记住良好的搜索体验不仅仅是技术实现,更需要关注用户的实际使用场景和需求。持续收集用户反馈,不断优化搜索算法和界面交互,才能打造出真正优秀的搜索功能。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考