构建智能旅游推荐:ollama-python用户行为分析

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

你是否还在为旅游推荐系统的同质化问题困扰?当用户输入"推荐适合家庭的海滨度假地"时,传统系统往往返回千篇一律的热门景点列表。本文将展示如何利用ollama-python构建基于用户行为分析的智能旅游推荐系统,通过对话历史追踪、行为特征提取和实时数据融合,实现真正个性化的旅行建议。读完本文你将掌握:

  • 使用ollama对话历史API构建用户行为档案
  • 通过嵌入向量(Embedding)量化用户偏好特征
  • 结合结构化输出与工具调用实现推荐逻辑
  • 完整的旅游推荐系统架构与代码实现

系统架构设计

智能旅游推荐系统需要解决三个核心问题:用户行为数据的有效收集、偏好特征的精准提取、以及动态推荐逻辑的实现。基于ollama-python构建的系统架构如下:

mermaid

技术栈选型

功能模块 ollama-python核心API 辅助技术
对话历史追踪 chat(messages=[]) Python列表/JSON文件
用户偏好提取 generate(format='json') JSON Schema验证
行为特征量化 embed(model='all-minilm') 余弦相似度计算
外部数据集成 tools=[Tool()] 景点信息API/天气服务
异步处理 AsyncClient() aiohttp/asyncio

用户行为数据收集

对话历史追踪实现

用户与推荐系统的每一次交互都蕴含潜在需求,通过ollama-python的对话历史管理可以完整记录交互过程:

from ollama import Client
import json
from datetime import datetime

class UserBehaviorTracker:
    def __init__(self, model="llama3.2"):
        self.client = Client()
        self.user_history = []
        self.behavior_log = []
        
    def track_interaction(self, user_input):
        # 追加用户输入到对话历史
        self.user_history.append({"role": "user", "content": user_input})
        
        # 获取模型响应
        response = self.client.chat(
            model="llama3.2",
            messages=self.user_history,
            stream=False
        )
        
        # 记录助手响应
        assistant_msg = response["message"]["content"]
        self.user_history.append({"role": "assistant", "content": assistant_msg})
        
        # 记录行为日志(包含时间戳和交互类型)
        self.behavior_log.append({
            "timestamp": datetime.now().isoformat(),
            "user_input": user_input,
            "intent": self._classify_intent(user_input),
            "response_time": response["total_duration"] / 1e9  # 转换为秒
        })
        
        return assistant_msg
    
    def _classify_intent(self, user_input):
        # 使用结构化输出解析用户意图
        schema = {
            "type": "object",
            "properties": {
                "intent": {"type": "string", "enum": ["查询", "推荐", "比较", "预订", "闲聊"]},
                "destination": {"type": "string"},
                "travel_type": {"type": "string", "enum": ["家庭", "情侣", "独自", "朋友"]},
                "budget": {"type": "number"}
            }
        }
        
        response = self.client.generate(
            model="llama3.2",
            prompt=f"解析用户查询意图: {user_input}",
            format={"type": "json", "schema": schema}
        )
        
        return json.loads(response["response"])

这段代码实现了基本的用户行为追踪功能,包括:

  • 完整对话历史记录
  • 交互意图自动分类
  • 响应时间统计
  • 结构化数据提取

多模态行为数据采集

现代旅游推荐需要处理多种类型的用户输入,ollama-python支持图像理解功能,可以分析用户上传的旅行照片来推断偏好:

from ollama import generate
import base64
from PIL import Image
import io

def analyze_travel_photo(image_path):
    # 读取并编码图像
    with open(image_path, "rb") as f:
        image_data = base64.b64encode(f.read()).decode("utf-8")
    
    # 定义图像分析结果的结构化输出
    schema = {
        "type": "object",
        "properties": {
            "scene_type": {"type": "string", "enum": ["海滩", "山脉", "城市", "古迹", "自然公园"]},
            "activities": {"type": "array", "items": {"type": "string"}},
            "crowd_level": {"type": "string", "enum": ["安静", "适中", "热闹"]},
            "architecture_style": {"type": "string"}
        }
    }
    
    response = generate(
        model="llava",  # 多模态模型
        prompt="分析这张旅行照片,描述场景类型、可能的活动和环境特征",
        images=[image_data],
        format={"type": "json", "schema": schema}
    )
    
    return json.loads(response["response"])

通过图像分析,系统可以获取用户过去旅行偏好的视觉线索,例如喜欢海滩还是山地、偏好自然景观还是城市建筑等,这些信息对于构建全面的用户画像至关重要。

用户偏好特征提取

行为嵌入向量生成

将用户行为转化为数值向量是实现个性化推荐的关键步骤。ollama-python的embed API可以将文本形式的用户行为记录转化为高维向量:

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

class UserPreferenceEmbedder:
    def __init__(self, model="all-minilm"):
        self.model = model
        self.user_embeddings = {}  # 存储用户历史行为嵌入
    
    def embed_behavior(self, user_id, behavior_texts):
        """将用户行为文本转化为嵌入向量"""
        # 如果是列表,直接处理;如果是单文本,转为列表
        if isinstance(behavior_texts, str):
            behavior_texts = [behavior_texts]
            
        response = embed(
            model=self.model,
            input=behavior_texts
        )
        
        embeddings = np.array(response["embeddings"])
        
        # 存储用户嵌入向量(取平均作为用户当前偏好向量)
        if user_id in self.user_embeddings:
            self.user_embeddings[user_id] = np.vstack(
                [self.user_embeddings[user_id], embeddings]
            ).mean(axis=0)
        else:
            self.user_embeddings[user_id] = embeddings.mean(axis=0)
            
        return self.user_embeddings[user_id]
    
    def compare_preferences(self, user_id1, user_id2):
        """比较两个用户的偏好相似度"""
        if user_id1 not in self.user_embeddings or user_id2 not in self.user_embeddings:
            return 0.0
            
        return cosine_similarity(
            self.user_embeddings[user_id1].reshape(1, -1),
            self.user_embeddings[user_id2].reshape(1, -1)
        )[0][0]

这个嵌入向量生成器可以:

  • 将用户文本行为记录转化为数值向量
  • 动态更新用户偏好特征
  • 计算用户间偏好相似度
  • 支持批量处理行为数据

推荐算法实现

基于嵌入向量的内容推荐

利用用户行为嵌入向量,我们可以实现基础的内容推荐功能:

import pandas as pd
from sklearn.metrics.pairwise import cosine_similarity

class TravelRecommender:
    def __init__(self, embedder,景点数据库):
        self.embedder = embedder  # 前面定义的UserPreferenceEmbedder实例
        self.景点数据库 = 景点数据库  # 包含景点描述的DataFrame
        self._precompute_destination_embeddings()
        
    def _precompute_destination_embeddings(self):
        """预计算所有景点的嵌入向量"""
        # 提取景点描述文本
        descriptions = self.景点数据库["description"].tolist()
        
        # 批量生成嵌入向量
        response = embed(
            model="all-minilm",
            input=descriptions
        )
        
        # 存储景点嵌入向量
        self.景点数据库["embedding"] = list(response["embeddings"])
        
    def recommend_destinations(self, user_id, top_n=5, filter_criteria=None):
        """基于用户偏好推荐景点"""
        if user_id not in self.embedder.user_embeddings:
            return []
            
        user_embedding = self.embedder.user_embeddings[user_id]
        
        # 计算用户与每个景点的相似度
        self.景点数据库["similarity"] = self.景点数据库["embedding"].apply(
            lambda x: cosine_similarity([user_embedding], [x])[0][0]
        )
        
        # 应用过滤条件
        filtered = self.景点数据库
        if filter_criteria:
            for key, value in filter_criteria.items():
                filtered = filtered[filtered[key] == value]
                
        # 返回相似度最高的top_n个景点
        recommendations = filtered.sort_values("similarity", ascending=False).head(top_n)
        
        return recommendations[["name", "location", "rating", "similarity"]].to_dict("records")

这个基础推荐器的工作流程是:

  1. 预计算所有景点的嵌入向量
  2. 获取用户当前偏好嵌入向量
  3. 计算余弦相似度匹配最佳景点
  4. 应用过滤条件(如预算、旅行类型)
  5. 返回排序后的推荐结果

结合工具调用的增强推荐

真实世界的旅游推荐需要实时数据支持,ollama-python的工具调用功能可以整合外部API:

from ollama import Client
import requests
import json

class EnhancedTravelRecommender(TravelRecommender):
    def __init__(self, embedder,景点数据库, api_keys):
        super().__init__(embedder,景点数据库)
        self.client = Client()
        self.api_keys = api_keys  # 存储外部API密钥
        
        # 定义可用工具
        self.tools = [
            {
                "name": "get_weather",
                "description": "获取指定地点的天气预报",
                "parameters": {
                    "type": "object",
                    "properties": {
                        "location": {"type": "string", "description": "城市名称"},
                        "days": {"type": "integer", "description": "预报天数", "default": 7}
                    },
                    "required": ["location"]
                }
            },
            {
                "name": "get_attraction_details",
                "description": "获取景点详细信息和实时人流数据",
                "parameters": {
                    "type": "object",
                    "properties": {
                        "attraction_id": {"type": "string", "description": "景点ID"},
                        "date": {"type": "string", "description": "访问日期,格式YYYY-MM-DD"}
                    },
                    "required": ["attraction_id", "date"]
                }
            }
        ]
    
    def get_weather(self, location, days=7):
        """调用天气API获取预报"""
        url = f"http://api.weatherapi.com/v1/forecast.json?key={self.api_keys['weather']}&q={location}&days={days}"
        response = requests.get(url)
        return response.json()
    
    def get_attraction_details(self, attraction_id, date):
        """调用景点信息API获取详情"""
        url = f"https://api.tripadvisor.com/api/partner/attractions/{attraction_id}/details"
        headers = {"Authorization": f"OAuth {self.api_keys['tripadvisor']}"}
        params = {"date": date}
        response = requests.get(url, headers=headers, params=params)
        return response.json()
    
    def intelligent_recommend(self, user_id, travel_dates, party_size):
        """智能推荐流程,结合工具调用"""
        # 1. 获取基础推荐
        base_recommendations = self.recommend_destinations(user_id)
        
        # 2. 准备系统提示
        system_prompt = f"""你是一个智能旅游推荐助手。基于以下初步推荐和用户信息,
        结合实时数据为用户提供最佳旅行建议。用户计划在{travel_dates}出行,同行{party_size}人。
        
        初步推荐: {base_recommendations}
        
        请考虑:
        1. 各目的地的天气情况是否适合旅行
        2. 景点在旅行日期的人流预测
        3. 是否需要调整推荐顺序或增加新目的地
        4. 提供具体的行程安排建议
        """
        
        # 3. 开始带工具调用的对话
        messages = [{"role": "system", "content": system_prompt}]
        
        while True:
            response = self.client.chat(
                model="llama3.2",
                messages=messages,
                tools=self.tools,
                stream=False
            )
            
            # 将模型响应添加到对话历史
            messages.append(response["message"])
            
            # 检查是否需要调用工具
            if not response["message"].get("tool_calls"):
                break
                
            # 处理工具调用
            for tool_call in response["message"]["tool_calls"]:
                function_name = tool_call["function"]["name"]
                arguments = json.loads(tool_call["function"]["arguments"])
                
                # 调用相应函数
                if function_name == "get_weather":
                    result = self.get_weather(**arguments)
                elif function_name == "get_attraction_details":
                    result = self.get_attraction_details(**arguments)
                else:
                    result = {"error": "未知工具"}
                    
                # 将工具调用结果添加到对话历史
                messages.append({
                    "role": "tool",
                    "content": json.dumps(result),
                    "tool_name": function_name
                })
        
        return response["message"]["content"]

这个增强推荐器增加了以下能力:

  • 调用外部API获取实时天气数据
  • 获取景点实时人流和可用性信息
  • 基于多轮工具调用动态优化推荐结果
  • 考虑旅行日期和同行人数等具体因素

完整系统实现

数据准备

首先准备一个简单的景点数据库:

# 准备景点数据库
景点数据库 = pd.DataFrame([
    {
        "name": "三亚亚龙湾",
        "location": "海南",
        "description": "中国最美的海滩之一,适合家庭度假,有清澈的海水和细腻的沙滩",
        "rating": 4.8,
        "price_level": "中高",
        "travel_type": "家庭,情侣",
        "activities": "游泳,日光浴,水上运动"
    },
    {
        "name": "张家界国家森林公园",
        "location": "湖南",
        "description": "壮观的砂岩峰林地貌,适合徒步和自然景观爱好者",
        "rating": 4.9,
        "price_level": "中等",
        "travel_type": "独自,朋友",
        "activities": "徒步,摄影,观景"
    },
    {
        "name": "北京故宫",
        "location": "北京",
        "description": "中国明清两代皇家宫殿,历史文化底蕴深厚",
        "rating": 4.7,
        "price_level": "中等",
        "travel_type": "家庭,独自",
        "activities": "观光,文化体验,摄影"
    },
    {
        "name": "丽江古城",
        "location": "云南",
        "description": "保存完好的历史文化古城,有独特的民族文化",
        "rating": 4.6,
        "price_level": "中等",
        "travel_type": "情侣,朋友",
        "activities": "观光,购物,美食,文化体验"
    },
    {
        "name": "桂林漓江",
        "location": "广西",
        "description": "以喀斯特地貌闻名的河流景观,适合乘船游览",
        "rating": 4.8,
        "price_level": "中等",
        "travel_type": "家庭,情侣,朋友",
        "activities": "乘船游览,摄影,徒步"
    }
])

系统集成

# 初始化组件
embedder = UserPreferenceEmbedder()
基础推荐器 = TravelRecommender(embedder, 景点数据库)

# API密钥配置(实际应用中应使用环境变量)
api_keys = {
    "weather": "your_weather_api_key",
    "tripadvisor": "your_tripadvisor_api_key"
}

增强推荐器 = EnhancedTravelRecommender(embedder, 景点数据库, api_keys)

# 用户交互示例
tracker = UserBehaviorTracker()
user_id = "user_123"

# 模拟用户交互
user_inputs = [
    "你好,我计划下个月去旅行",
    "我想找一个适合家庭的海滨度假地",
    "我们有2个小孩,预算中等",
    "想了解一下三亚怎么样?",
    "有什么好玩的景点推荐吗?",
    "天气怎么样?需要带什么衣服?"
]

for input_text in user_inputs:
    print(f"用户: {input_text}")
    response = tracker.track_interaction(input_text)
    
    # 记录用户行为到嵌入向量
    embedder.embed_behavior(user_id, input_text)
    
    print(f"系统: {response}\n")

# 生成最终推荐
print("===== 个性化旅行推荐 =====")
print(增强推荐器.intelligent_recommend(
    user_id="user_123",
    travel_dates="2025-07-10至2025-07-17",
    party_size=4
))

系统优化与评估

性能优化策略

为了提升推荐系统性能,可以实施以下优化:

class OptimizedTravelRecommender(EnhancedTravelRecommender):
    def __init__(self, embedder,

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

更多推荐