Ollama Python嵌入功能:文本向量化应用

Ollama Python嵌入功能:文本向量化应用

【免费下载链接】ollama-python 【免费下载链接】ollama-python 项目地址: https://gitcode.com/GitHub_Trending/ol/ollama-python

Ollama Python库通过其强大的Embeddings功能,为开发者提供了简单高效的文本向量化解决方案。该功能基于深度学习模型的编码器架构,将自然语言文本转换为高维数值向量,这些向量在向量空间中保持语义相似性,使得相似的文本在向量空间中距离更近。本文详细介绍了Embeddings功能的技术原理、API接口、多样化应用场景以及性能优化策略。

Embeddings功能原理与应用场景

在现代人工智能应用中,文本向量化技术已成为构建智能系统的核心基础。Ollama Python库通过其强大的Embeddings功能,为开发者提供了简单高效的文本向量化解决方案。本节将深入探讨Embeddings功能的技术原理、实现机制以及在实际应用中的多样化场景。

技术原理与架构设计

Ollama的Embeddings功能基于深度学习模型的编码器架构,将自然语言文本转换为高维数值向量。这些向量在向量空间中保持语义相似性,使得相似的文本在向量空间中距离更近。

mermaid

向量生成流程

Ollama的Embeddings生成过程遵循以下技术路径:

  1. 文本预处理:输入文本经过标准化处理,包括大小写转换、标点符号处理等
  2. 分词编码:使用模型的词汇表将文本转换为token序列
  3. 特征提取:通过多层Transformer编码器提取深层语义特征
  4. 池化操作:采用平均池化或最大池化策略聚合序列特征
  5. 归一化输出:对生成的向量进行L2归一化,确保向量模长为1

核心API接口详解

Ollama Python库提供了两个主要的Embeddings接口:embed()embeddings(),后者已被标记为弃用,推荐使用前者。

embed()方法参数说明
def embed(
    self,
    model: str = '',
    input: Union[str, Sequence[str]] = '',
    truncate: Optional[bool] = None,
    options: Optional[Union[Mapping[str, Any], Options]] = None,
    keep_alive: Optional[Union[float, str]] = None,
) -> EmbedResponse
参数名类型必需说明
modelstr使用的模型名称,如'llama3.2'
inputUnion[str, Sequence[str]]输入文本或文本列表
truncateOptional[bool]是否截断超长文本
optionsOptional[Options]模型推理选项
keep_aliveOptional[Union[float, str]]模型保持活跃时间
响应数据结构

Embeddings请求返回EmbedResponse对象,包含以下关键字段:

class EmbedResponse(SubscriptableBaseModel):
    embeddings: Sequence[Sequence[float]]
    '生成的向量列表,每个输入对应一个向量'

class EmbeddingsResponse(SubscriptableBaseModel):
    embedding: Sequence[float]
    '单个向量(已弃用接口)'

多样化应用场景

1. 语义搜索与检索

Embeddings在搜索系统中发挥着核心作用,通过向量相似度计算实现精准的内容匹配。

from ollama import embed
import numpy as np
from sklearn.metrics.pairwise import cosine_similarity

# 生成文档向量库
documents = [
    "机器学习是人工智能的核心技术",
    "深度学习基于神经网络架构",
    "自然语言处理处理文本数据"
]

doc_embeddings = []
for doc in documents:
    response = embed(model='llama3.2', input=doc)
    doc_embeddings.append(response['embeddings'][0])

# 查询处理
query = "什么是人工智能技术"
query_response = embed(model='llama3.2', input=query)
query_embedding = query_response['embeddings'][0]

# 相似度计算
similarities = cosine_similarity([query_embedding], doc_embeddings)[0]
most_similar_idx = np.argmax(similarities)

print(f"最相关文档: {documents[most_similar_idx]}")
print(f"相似度: {similarities[most_similar_idx]:.4f}")
2. 文本分类与聚类

利用Embeddings特征进行无监督聚类或有监督分类任务。

from sklearn.cluster import KMeans
from sklearn.decomposition import PCA
import matplotlib.pyplot as plt

# 生成文本向量
texts = ["科技新闻A", "体育新闻B", "科技新闻C", "财经新闻D", "体育新闻E"]
embeddings = []

for text in texts:
    response = embed(model='llama3.2', input=text)
    embeddings.append(response['embeddings'][0])

# K-means聚类
kmeans = KMeans(n_clusters=3, random_state=42)
clusters = kmeans.fit_predict(embeddings)

# 可视化降维
pca = PCA(n_components=2)
reduced_embeddings = pca.fit_transform(embeddings)

plt.figure(figsize=(10, 6))
for i, cluster in enumerate(clusters):
    plt.scatter(reduced_embeddings[i, 0], reduced_embeddings[i, 1], 
                c=f'C{cluster}', label=f'Cluster {cluster}' if i == 0 else "")
    plt.annotate(texts[i], (reduced_embeddings[i, 0], reduced_embeddings[i, 1]))

plt.title('文本聚类可视化')
plt.xlabel('PCA Component 1')
plt.ylabel('PCA Component 2')
plt.legend()
plt.show()
3. 推荐系统构建

基于内容相似度的推荐系统实现。

class ContentBasedRecommender:
    def __init__(self, model_name='llama3.2'):
        self.model_name = model_name
        self.item_embeddings = {}
        self.item_contents = {}
    
    def add_item(self, item_id, content):
        """添加项目到推荐系统"""
        response = embed(model=self.model_name, input=content)
        self.item_embeddings[item_id] = response['embeddings'][0]
        self.item_contents[item_id] = content
    
    def recommend(self, query_content, top_k=5):
        """基于内容推荐相似项目"""
        response = embed(model=self.model_name, input=query_content)
        query_embedding = response['embeddings'][0]
        
        similarities = {}
        for item_id, embedding in self.item_embeddings.items():
            similarity = np.dot(query_embedding, embedding) / (
                np.linalg.norm(query_embedding) * np.linalg.norm(embedding))
            similarities[item_id] = similarity
        
        # 返回最相似的项目
        recommended_ids = sorted(similarities.items(), 
                               key=lambda x: x[1], reverse=True)[:top_k]
        
        return [(item_id, similarities[item_id], self.item_contents[item_id]) 
                for item_id, similarity in recommended_ids]

# 使用示例
recommender = ContentBasedRecommender()
recommender.add_item(1, "Python编程教程")
recommender.add_item(2, "机器学习实战")
recommender.add_item(3, "深度学习框架比较")

recommendations = recommender.recommend("人工智能学习资料", top_k=2)
for item_id, similarity, content in recommendations:
    print(f"推荐ID: {item_id}, 相似度: {similarity:.4f}, 内容: {content}")
4. 异常检测与去重

识别异常文本或检测重复内容。

def detect_anomalies(texts, threshold=0.3):
    """检测异常文本"""
    embeddings = []
    for text in texts:
        response = embed(model='llama3.2', input=text)
        embeddings.append(response['embeddings'][0])
    
    # 计算平均向量
    avg_embedding = np.mean(embeddings, axis=0)
    
    anomalies = []
    for i, embedding in enumerate(embeddings):
        similarity = np.dot(avg_embedding, embedding) / (
            np.linalg.norm(avg_embedding) * np.linalg.norm(embedding))
        
        if similarity < threshold:
            anomalies.append((i, texts[i], similarity))
    
    return anomalies

def remove_duplicates(texts, similarity_threshold=0.95):
    """去除重复文本"""
    embeddings = []
    for text in texts:
        response = embed(model='llama3.2', input=text)
        embeddings.append(response['embeddings'][0])
    
    unique_texts = []
    seen_embeddings = []
    
    for i, (text, embedding) in enumerate(zip(texts, embeddings)):
        is_duplicate = False
        for seen_embedding in seen_embeddings:
            similarity = np.dot(embedding, seen_embedding) / (
                np.linalg.norm(embedding) * np.linalg.norm(seen_embedding))
            
            if similarity > similarity_threshold:
                is_duplicate = True
                break
        
        if not is_duplicate:
            unique_texts.append(text)
            seen_embeddings.append(embedding)
    
    return unique_texts

性能优化策略

批量处理优化

Ollama支持批量文本处理,显著提升处理效率。

# 单条处理(效率较低)
single_responses = []
for text in large_text_collection:
    response = embed(model='llama3.2', input=text)
    single_responses.append(response)

# 批量处理(推荐)
batch_response = embed(model='llama3.2', input=large_text_collection)
batch_embeddings = batch_response['embeddings']
缓存机制实现
from functools import lru_cache
import hashlib

@lru_cache(maxsize=1000)
def get_cached_embedding(text, model='llama3.2'):
    """带缓存的Embedding获取函数"""
    cache_key = hashlib.md5(f"{model}_{text}".encode()).hexdigest()
    
    response = embed(model=model, input=text)
    return response['embeddings'][0]

# 使用缓存
text = "需要向量化的文本"
embedding = get_cached_embedding(text)

实际部署考虑

模型选择策略

不同模型在Embeddings任务上的表现差异:

模型名称向量维度适用场景性能特点
llama3.24096通用场景平衡性能与精度
mistral4096多语言优秀的跨语言能力
gemma35120高质量需求更高的语义理解能力
错误处理与重试机制
import time
from ollama import ResponseError

def robust_embedding(text, model='llama3.2', max_retries=3):
    """带重试机制的Embedding获取"""
    for attempt in range(max_retries):
        try:
            response = embed(model=model, input=text)
            return response['embeddings'][0]
        except ResponseError as e:
            if attempt == max_retries - 1:
                raise
            print(f"Attempt {attempt + 1} failed: {e}")
            time.sleep(2 ** attempt)  # 指数退避
        except Exception as e:
            print(f"Unexpected error: {e}")
            raise

通过上述技术原理和应用场景的深入分析,可以看出Ollama Python库的Embeddings功能为开发者提供了强大而灵活的文本向量化解决方案。无论是构建搜索系统、推荐引擎,还是进行文本分析和处理,这一功能都能发挥关键作用,为人工智能应用提供坚实的语义理解基础。

单文本与批量文本嵌入实现

Ollama Python库提供了强大的文本嵌入功能,支持单文本和批量文本的向量化处理。通过简洁的API设计,开发者可以轻松地将自然语言文本转换为高维向量表示,为语义搜索、相似度计算、聚类分析等应用场景提供基础支持。

单文本嵌入实现

单文本嵌入是最基础的嵌入操作,将单个文本字符串转换为向量表示。Ollama提供了直观的API接口:

from ollama import embed

# 单文本嵌入示例
response = embed(model='llama3.2', input='自然语言处理是人工智能的重要分支')
print(f"嵌入向量维度: {len(response['embeddings'][0])}")
print(f"嵌入向量前10维: {response['embeddings'][0][:10]}")

单文本嵌入的核心参数说明:

参数类型说明必填
modelstring使用的嵌入模型名称
inputstring要嵌入的文本内容
optionsdict模型配置选项
keep_alivefloat/string模型保持活跃时间

单文本嵌入的响应结构包含完整的嵌入向量信息:

{
    "embeddings": [
        [0.123, -0.456, 0.789, ...]  # 768维或更高维度的浮点数向量
    ],
    "model": "llama3.2",
    "created_at": "2024-01-01T12:00:00.000Z",
    "total_duration": 15000000,
    "load_duration": 5000000,
    "prompt_eval_duration": 10000000
}

批量文本嵌入实现

批量文本嵌入允许一次性处理多个文本,显著提高处理效率,特别适合大规模数据处理场景:

from ollama import embed

# 批量文本嵌入示例
texts = [
    "机器学习是人工智能的核心技术",
    "深度学习基于神经网络架构",
    "自然语言处理让计算机理解人类语言"
]

response = embed(model='llama3.2', input=texts)
print(f"处理文本数量: {len(response['embeddings'])}")
print(f"每个向量的维度: {len(response['embeddings'][0])}")

# 遍历所有嵌入结果
for i, embedding in enumerate(response['embeddings']):
    print(f"文本{i+1}嵌入完成,向量长度: {len(embedding)}")

批量嵌入的优势对比:

特性单文本嵌入批量文本嵌入
处理效率较低高(减少网络开销)
适用场景实时交互批量数据处理
资源消耗每次请求独立资源共享优化
API调用次数多次单次

高级配置选项

Ollama嵌入功能支持丰富的配置选项,通过options参数进行精细控制:

from ollama import embed

# 带配置选项的嵌入示例
response = embed(
    model='llama3.2',
    input=['文本语义表示学习'],
    options={
        'temperature': 0.1,
        'num_ctx': 2048,
        'embedding_only': True
    }
)

常用配置选项说明:

选项类型默认值说明
embedding_onlyboolFalse仅生成嵌入,不进行其他处理
num_ctxint2048上下文窗口大小
temperaturefloat0.8生成随机性控制
num_threadint自动CPU线程数

错误处理与性能优化

在实际应用中,合理的错误处理和性能优化至关重要:

from ollama import embed, ResponseError
import time

def safe_embedding(texts, model='llama3.2', max_retries=3):
    """安全的嵌入处理函数,包含重试机制"""
    for attempt in range(max_retries):
        try:
            start_time = time.time()
            response = embed(model=model, input=texts)
            duration = time.time() - start_time
            print(f"嵌入完成,耗时: {duration:.2f}秒")
            return response
        except ResponseError as e:
            print(f"尝试 {attempt + 1} 失败: {e}")
            if attempt == max_retries - 1:
                raise
            time.sleep(2 ** attempt)  # 指数退避

# 使用安全嵌入函数
texts = ["示例文本1", "示例文本2", "示例文本3"]
result = safe_embedding(texts)

性能优化建议:

  1. 批量处理:尽可能使用批量嵌入减少API调用次数
  2. 连接复用:使用自定义Client实例复用HTTP连接
  3. 超时设置:根据网络状况设置合理的超时时间
  4. 缓存策略:对重复文本实施嵌入结果缓存

实际应用场景

单文本与批量文本嵌入在多个实际场景中发挥重要作用:

# 语义相似度计算
def calculate_similarity(text1, text2, model='llama3.2'):
    """计算两个文本的语义相似度"""
    from numpy import dot
    from numpy.linalg import norm
    
    response = embed(model=model, input=[text1, text2])
    vec1, vec2 = response['embeddings']
    
    # 余弦相似度计算
    similarity = dot(vec1, vec2) / (norm(vec1) * norm(vec2))
    return similarity

# 文本聚类分析
def text_clustering(texts, model='llama3.2'):
    """基于嵌入向量的文本聚类"""
    from sklearn.cluster import KMeans
    import numpy as np
    
    response = embed(model=model, input=texts)
    embeddings = np.array(response['embeddings'])
    
    # K-means聚类
    kmeans = KMeans(n_clusters=3, random_state=42)
    clusters = kmeans.fit_predict(embeddings)
    
    return clusters, embeddings

通过上述实现,开发者可以充分利用Ollama的嵌入功能,构建高效的文本处理流水线,为各种NLP应用提供强大的语义理解能力。

嵌入结果的处理与分析技巧

在Ollama Python库中,嵌入功能生成的向量化结果需要经过专业的处理和分析才能发挥最大价值。嵌入向量是高维空间中的数值表示,正确的处理方法能够显著提升语义搜索、相似度计算和聚类分析的效果。

嵌入结果的数据结构解析

Ollama的嵌入功能返回EmbedResponse对象,其中包含关键的embeddings字段。这是一个二维序列,每个内部序列代表一个输入文本的向量表示:

from ollama import embed

# 单文本嵌入
response = embed(model='llama3.2', input='自然语言处理技术')
embedding_vector = response.embeddings[0]  # 获取第一个嵌入向量

# 批量文本嵌入
texts = ['机器学习', '深度学习', '人工智能']
batch_response = embed(model='llama3.2', input=texts)
all_embeddings = batch_response.embeddings  # 获取所有嵌入向量

嵌入向量的典型维度取决于所使用的模型,通常在384到4096维之间。了解向量的维度对于后续的存储和计算至关重要。

向量归一化处理

原始嵌入向量通常需要进行归一化处理,以确保相似度计算的准确性:

import numpy as np

def normalize_embeddings(embeddings):
    """对嵌入向量进行L2归一化"""
    if isinstance(embeddings, list):
        embeddings = np.array(embeddings)
    
    norms = np.linalg.norm(embeddings, axis=1, keepdims=True)
    norms[norms == 0] = 1  # 避免除以零
    return embeddings / norms

# 应用归一化
normalized_vectors = normalize_embeddings(all_embeddings)

归一化后的向量在进行余弦相似度计算时更加准确,因为余弦相似度本质上就是归一化向量的点积。

相似度计算与分析

相似度计算是嵌入分析的核心环节,常用的方法包括:

from sklearn.metrics.pairwise import cosine_similarity
import numpy as np

def calculate_similarity_matrix(embeddings):
    """计算嵌入向量之间的相似度矩阵"""
    normalized = normalize_embeddings(embeddings)
    similarity_matrix = cosine_similarity(normalized)
    return similarity_matrix

def find_most_similar(query_embedding, candidate_embeddings, top_k=5):
    """查找与查询向量最相似的候选向量"""
    similarities = cosine_similarity([query_embedding], candidate_embeddings)[0]
    top_indices = np.argsort(similarities)[-top_k:][::-1]
    return top_indices, similarities[top_indices]

# 示例使用
similarity_matrix = calculate_similarity_matrix(all_embeddings)
print("相似度矩阵:\n", similarity_matrix)

聚类分析与可视化

对于大量嵌入向量,聚类分析可以帮助发现文本之间的自然分组:

from sklearn.cluster import KMeans
from sklearn.decomposition import PCA
import matplotlib.pyplot as plt

def cluster_embeddings(embeddings, n_clusters=3):
    """对嵌入向量进行K-means聚类"""
    kmeans = KMeans(n_clusters=n_clusters, random_state=42)
    clusters = kmeans.fit_predict(embeddings)
    return clusters, kmeans.cluster_centers_

def visualize_clusters(embeddings, clusters, texts):
    """可视化聚类结果(降维到2D)"""
    pca = PCA(n_components=2)
    reduced = pca.fit_transform(embeddings)
    
    plt.figure(figsize=(10, 8))
    scatter = plt.scatter(reduced[:, 0], reduced[:, 1], c=clusters, cmap='viridis')
    plt.colorbar(scatter)
    
    # 添加文本标签
    for i, text in enumerate(texts):
        plt.annotate(text[:20] + '...', (reduced[i, 0], reduced[i, 1]), fontsize=8)
    
    plt.title('嵌入向量聚类可视化')
    plt.xlabel('PCA Component 1')
    plt.ylabel('PCA Component 2')
    plt.show()

# 应用聚类分析
clusters, centers = cluster_embeddings(normalized_vectors, n_clusters=2)
visualize_clusters(normalized_vectors, clusters, texts)

异常值检测与质量控制

嵌入结果的质量直接影响下游任务的效果,需要进行异常值检测:

def detect_anomalies(embeddings, threshold=2.0):
    """检测嵌入向量中的异常值"""
    from scipy import stats
    import numpy as np
    
    # 计算每个向量的模长
    norms = np.linalg.norm(embeddings, axis=1)
    
    # 使用Z-score检测异常值
    z_scores = np.abs(stats.zscore(norms))
    anomalies = np.where(z_scores > threshold)[0]
    
    return anomalies, z_scores

def quality_check(embeddings, min_norm=0.1, max_norm=10.0):
    """嵌入向量质量检查"""
    norms = np.linalg.norm(embeddings, axis=1)
    
    quality_issues = []
    for i, norm in enumerate(norms):
        if norm < min_norm:
            quality_issues.append(f"向量{i}: 模长过小 ({norm:.4f})")
        elif norm > max_norm:
            quality_issues.append(f"向量{i}: 模长过大 ({norm:.4f})")
    
    return quality_issues, norms

# 执行质量检查
anomalies, z_scores = detect_anomalies(all_embeddings)
issues, norms = quality_check(all_embeddings)

print(f"检测到异常值索引: {anomalies}")
print(f"质量检查结果: {issues}")

性能优化与批量处理

对于大规模嵌入任务,需要优化处理流程:

import numpy as np
from concurrent.futures import ThreadPoolExecutor
import time

def batch_embed_texts(texts, model_name, batch_size=32):
    """批量处理文本嵌入,支持大文本集合"""
    all_embeddings = []
    
    for i in range(0, len(texts), batch_size):
        batch = texts[i:i + batch_size]
        try:
            response = embed(model=model_name, input=batch)
            all_embeddings.extend(response.embeddings)
            time.sleep(0.1)  # 避免请求过载
        except Exception as e:
            print(f"处理批次 {i//batch_size + 1} 时出错: {e}")
            # 添加空向量作为占位符
            all_embeddings.extend([np.zeros(768)] * len(batch))
    
    return all_embeddings

def parallel_similarity_calculation(query_vectors, candidate_vectors, batch_size=100):
    """并行计算相似度,提升大规模计算性能"""
    def calculate_batch_similarity(batch_indices):
        batch_candidates = candidate_vectors[batch_indices]
        return cosine_similarity(query_vectors, batch_candidates)
    
    n_candidates = len(candidate_vectors)
    all_similarities = []
    
    with ThreadPoolExecutor() as executor:
        futures = []
        for i in range(0, n_candidates, batch_size):
            batch_indices = slice(i, min(i + batch_size, n_candidates))
            futures.append(executor.submit(calculate_batch_similarity, batch_indices))
        
        for future in futures:
            all_similarities.append(future.result())
    
    return np.concatenate(all_similarities, axis=1)

结果持久化与缓存策略

为了提升效率和避免重复计算,需要实现合理的缓存机制:

import pickle
import hashlib
import os
from pathlib import Path

class EmbeddingCache:
    def __init__(self, cache_dir=".embedding_cache"):
        self.cache_dir = Path(cache_dir)
        self.cache_dir.mkdir(exist_ok=True)
    
    def _get_cache_key(self, text, model_name):
        """生成缓存键"""
        content = f"{model_name}:{text}"
        return hashlib.md5(content.encode()).hexdigest()
    
    def get_embedding(self, text, model_name):
        """获取缓存中的嵌入向量"""
        cache_key = self._get_cache_key(text, model_name)
        cache_file = self.cache_dir / f"{cache_key}.pkl"
        
        if cache_file.exists():
            with open(cache_file, 'rb') as f:
                return pickle.load(f)
        return None
    
    def save_embedding(self, text, model_name, embedding):
        """保存嵌入向量到缓存"""
        cache_key = self._get_cache_key(text, model_name)
        cache_file = self.cache_dir / f"{cache_key}.pkl"
        
        with open(cache_file, 'wb') as f:
            pickle.dump(embedding, f)
    
    def batch_get_embeddings(self, texts, model_name):
        """批量获取缓存"""
        cached = {}
        missing = []
        
        for text in texts:
            embedding = self.get_embedding(text, model_name)
            if embedding is not None:
                cached[text] = embedding
            else:
                missing.append(text)
        
        return cached, missing

# 使用缓存机制
cache = EmbeddingCache()
cached_embeddings, missing_texts = cache.batch_get_embeddings(texts, 'llama3.2')

if missing_texts:
    new_embeddings = embed(model='llama3.2', input=missing_texts)
    for text, embedding in zip(missing_texts, new_embeddings.embeddings):
        cache.save_embedding(text, 'llama3.2', embedding)

通过上述技巧和方法,您可以有效地处理和分析Ollama生成的嵌入结果,为后续的语义搜索、推荐系统、文本分类等应用奠定坚实基础。正确的处理流程不仅提升分析效率,还能确保下游任务获得准确可靠的结果。

语义搜索与相似度计算实践

在文本向量化的应用中,语义搜索和相似度计算是两个核心功能。通过Ollama Python库的嵌入功能,我们可以将文本转换为高维向量表示,进而实现基于语义的搜索和相似度比较。本节将深入探讨如何使用Ollama进行语义搜索和相似度计算的实践应用。

嵌入向量基础概念

嵌入向量是将文本数据映射到高维向量空间的技术表示。在语义搜索中,相似的文本会在向量空间中彼此靠近,这使得我们可以通过计算向量之间的距离来度量文本之间的语义相似性。

from ollama import embed
import numpy as np

# 生成文本嵌入向量
def get_embedding(text, model='llama3.2'):
    response = embed(model=model, input=text)
    return np.array(response['embeddings'][0])

# 示例文本
text1 = "人工智能技术发展迅速"
text2 = "AI技术正在快速发展"
text3 = "今天的天气很好"

# 获取嵌入向量
embedding1 = get_embedding(text1)
embedding2 = get_embedding(text2) 
embedding3 = get_embedding(text3)

print(f"向量维度: {embedding1.shape}")
print(f"文本1向量示例: {embedding1[:5]}")

相似度计算方法

在语义搜索中,常用的相似度计算方法包括余弦相似度、欧几里得距离和点积等。这些方法各有特点,适用于不同的应用场景。

import numpy as np
from sklearn.metrics.pairwise import cosine_similarity

def cosine_similarity_custom(vec1, vec2):
    """计算两个向量的余弦相似度"""
    dot_product = np.dot(vec1, vec2)
    norm1 = np.linalg.norm(vec1)
    norm2 = np.linalg.norm(vec2)
    return dot_product / (norm1 * norm2)

def euclidean_distance(vec1, vec2):
    """计算欧几里得距离"""
    return np.linalg.norm(vec1 - vec2)

def manhattan_distance(vec1, vec2):
    """计算曼哈顿距离"""
    return np.sum(np.abs(vec1 - vec2))

# 计算不同文本之间的相似度
cos_sim_12 = cosine_similarity_custom(embedding1, embedding2)
cos_sim_13 = cosine_similarity_custom(embedding1, embedding3)

print(f"文本1和文本2的余弦相似度: {cos_sim_12:.4f}")
print(f"文本1和文本3的余弦相似度: {cos_sim_13:.4f}")

构建语义搜索引擎

基于嵌入向量的语义搜索引擎可以理解查询的语义意图,而不仅仅是关键词匹配。下面是一个简单的语义搜索实现:

class SemanticSearchEngine:
    def __init__(self, model='llama3.2'):
        self.model = model
        self.documents = []
        self.embeddings = []
    
    def add_document(self, text):
        """添加文档到搜索索引"""
        embedding = get_embedding(text, self.model)
        self.documents.append(text)
        self.embeddings.append(embedding)
    
    def search(self, query, top_k=5):
        """执行语义搜索"""
        query_embedding = get_embedding(query, self.model)
        similarities = []
        
        for doc_embedding in self.embeddings:
            similarity = cosine_similarity_custom(query_embedding, doc_embedding)
            similarities.append(similarity)
        
        # 获取最相似的前k个结果
        indices = np.argsort(similarities)[::-1][:top_k]
        results = [(self.documents[i], similarities[i]) for i in indices]
        
        return results

# 使用示例
search_engine = SemanticSearchEngine()

# 添加文档
documents = [
    "机器学习是人工智能的重要分支",
    "深度学习基于神经网络技术",
    "自然语言处理让计算机理解人类语言",
    "计算机视觉处理图像和视频数据",
    "强化学习通过试错来学习最优策略"
]

for doc in documents:
    search_engine.add_document(doc)

# 执行搜索
query = "AI中的神经网络技术"
results = search_engine.search(query)

print("搜索结果:")
for i, (doc, score) in enumerate(results, 1):
    print(f"{i}. 相似度: {score:.4f} - {doc}")

相似度矩阵分析

对于文档集合,我们可以构建相似度矩阵来可视化文档之间的语义关系:

def build_similarity_matrix(documents, model='llama3.2'):
    """构建文档相似度矩阵"""
    n = len(documents)
    embeddings = [get_embedding(doc, model) for doc in documents]
    matrix = np.zeros((n, n))
    
    for i in range(n):
        for j in range(n):
            matrix[i][j] = cosine_similarity_custom(embeddings[i], embeddings[j])
    
    return matrix

# 构建相似度矩阵
similarity_matrix = build_similarity_matrix(documents)

print("文档相似度矩阵:")
print(similarity_matrix)

高级相似度计算技巧

在实际应用中,我们可能需要更复杂的相似度计算策略:

def weighted_similarity(query_embedding, doc_embedding, weights=None):
    """带权重的相似度计算"""
    if weights is None:
        weights = np.ones_like(query_embedding)
    
    # 应用权重
    weighted_query = query_embedding * weights
    weighted_doc = doc_embedding * weights
    
    return cosine_similarity_custom(weighted_query, weighted_doc)

def semantic_clustering(documents, threshold=0.8):
    """基于语义相似度的文档聚类"""
    embeddings = [get_embedding(doc) for doc in documents]
    clusters = []
    visited = set()
    
    for i, emb_i in enumerate(embeddings):
        if i in visited:
            continue
        
        cluster = [i]
        visited.add(i)
        
        for j, emb_j in enumerate(embeddings):
            if j not in visited and cosine_similarity_custom(emb_i, emb_j) > threshold:
                cluster.append(j)
                visited.add(j)
        
        clusters.append(cluster)
    
    return clusters

# 文档聚类示例
clusters = semantic_clustering(documents, threshold=0.7)
print("文档聚类结果:")
for i, cluster in enumerate(clusters):
    print(f"聚类 {i+1}: {[documents[idx] for idx in cluster]}")

性能优化策略

在处理大规模数据时,性能优化至关重要:

from sklearn.neighbors import NearestNeighbors
import faiss  # 高性能相似度搜索库

class OptimizedSemanticSearch:
    def __init__(self, model='llama3.2', use_faiss=True):
        self.model = model
        self.use_faiss = use_faiss
        self.documents = []
        self.embeddings = None
        self.index = None
    
    def build_index(self, documents):
        """构建高效的搜索索引"""
        self.documents = documents
        embeddings = [get_embedding(doc, self.model) for doc in documents]
        self.embeddings = np.array(embeddings)
        
        if self.use_faiss and len(embeddings) > 0:
            # 使用FAISS进行高效相似度搜索
            dimension = self.embeddings.shape[1]
            self.index = faiss.IndexFlatL2(dimension)
            self.index.add(self.embeddings.astype('float32'))
        else:
            # 使用scikit-learn的最近邻搜索
            self.index = NearestNeighbors(n_neighbors=5, metric='cosine')
            self.index.fit(self.embeddings)
    
    def search(self, query, top_k=5):
        """高效搜索"""
        query_embedding = get_embedding(query, self.model).reshape(1, -1)
        
        if self.use_faiss and self.index is not None:
            # FAISS搜索
            distances, indices = self.index.search(query_embedding.astype('float32'), top_k)
            results = [(self.documents[i], 1 - distances[0][j]) 
                      for j, i in enumerate(indices[0])]
        else:
            # scikit-learn搜索
            distances, indices = self.index.kneighbors(query_embedding)
            results = [(self.documents[i], 1 - distances[0][j]) 
                      for j, i in enumerate(indices[0])]
        
        return results

# 性能优化示例
optimized_searcher = OptimizedSemanticSearch(use_faiss=True)
optimized_searcher.build_index(documents)

# 执行高效搜索
results = optimized_searcher.search("人工智能技术", top_k=3)
print("优化后的搜索结果:")
for doc, score in results:
    print(f"相似度: {score:.4f} - {doc}")

相似度阈值设定

在实际应用中,合理设定相似度阈值对于过滤结果至关重要:

def adaptive_thresholding(similarities, method='mean_std'):
    """自适应阈值设定"""
    if method == 'mean_std':
        mean = np.mean(similarities)
        std = np.std(similarities)
        return mean + std
    elif method == 'percentile':
        return np.percentile(similarities, 75)
    else:
        return 0.7  # 默认阈值

def filter_results_by_threshold(results, threshold_method='mean_std'):
    """根据自适应阈值过滤结果"""
    similarities = [score for _, score in results]
    threshold = adaptive_thresholding(similarities, threshold_method)
    
    filtered_results = [(doc, score) for doc, score in results if score >= threshold]
    return filtered_results, threshold

# 阈值过滤示例
all_results = search_engine.search("机器学习", top_k=10)
filtered_results, threshold = filter_results_by_threshold(all_results)

print(f"自适应阈值: {threshold:.4f}")
print("过滤后的结果:")
for doc, score in filtered_results:
    print(f"相似度: {score:.4f} - {doc}")

通过上述实践,我们可以看到Ollama Python库在语义搜索和相似度计算方面的强大能力。这些技术可以应用于文档检索、推荐系统、问答系统等多个领域,为用户提供更加智能和精准的搜索体验。

总结

通过深入分析Ollama Python库的Embeddings功能,我们可以看到这一技术为文本向量化提供了强大而灵活的解决方案。从技术原理到实际应用,从单文本处理到批量优化,Embeddings功能在语义搜索、推荐系统、文本分类和聚类分析等多个领域都能发挥关键作用。合理的错误处理、性能优化和缓存策略进一步提升了系统的稳定性和效率,为人工智能应用提供了坚实的语义理解基础。

【免费下载链接】ollama-python 【免费下载链接】ollama-python 项目地址: https://gitcode.com/GitHub_Trending/ol/ollama-python

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值