
简介本资源是一份面向计算机专业本科生与深度学习初学者的毕业设计文档聚焦于构建智能化、个性化的音乐推荐系统解决大数据环境下用户精准获取偏好音乐的痛点。文档完整呈现了基于Python与Django框架的系统设计全过程涵盖自动编码器与卷积神经网络融合的音频/歌词特征提取、内容特征与协同过滤紧耦合建模、用户喜好分析及B/S架构实现等核心环节并附有摘要、中英文关键词、目录、技术选型说明Python、MySQL、KNNBaseline等及详细章节论述。资源为单个1.18MB的DOCX文件结构规范、图文结合含绪论、算法研究、系统设计与实现等完整毕业论文模块可直接用于课程设计参考、毕设开题与方案深化。目前已有548人学习下载内容扎实、逻辑清晰特别适合需要快速掌握深度学习在推荐场景落地路径的学习者。1. 为什么用 Django 搭深度学习音乐推荐系统不是 Flask也不是 FastAPI更不是纯 PyTorch Web 服务你手头有一堆用户听歌行为日志、千万级歌曲元数据、MFCC Chroma 提取的音频特征还想跑一个带注意力机制的双塔模型User Tower Item Tower做向量召回——但上线时卡在「怎么把模型预测嵌进真实业务流」这一步很多人第一反应是写个 Flask API接上torch.load()和model.eval()再用 Gunicorn 跑起来。结果上线三天并发一过 50CPU 爆到 98%用户反馈“点一次推荐要等 8 秒”运维半夜打电话问“你那个 /api/recommend 是不是在后台偷偷训练模型”这不是模型的问题是架构选型的硬伤。Flask 默认单线程、无连接池、无中间件生命周期管理FastAPI 虽快但对 Django 生态里已有的用户认证django.contrib.auth、权限控制django-guardian、后台管理django-admin、日志审计django-auditlog全得重写一遍而纯 PyTorch Web 服务连用户历史播放记录的分页查询、收藏夹同步、设备绑定这些基础功能都得自己造轮子。本项目标题里的「基于 Python Django 深度学习的音乐推荐方法研究系统设计与实现」核心不在“用 Django 写了个网页”而在于用 Django 的请求-响应生命周期接管深度学习服务的调度边界模型加载只在 Django 启动时做一次AppConfig.ready()推理请求走异步任务队列Celery Redis特征预处理复用 Django ORM 的select_related()和prefetch_related()避免 N1 查询推荐结果存入django.contrib.postgres.fields.JSONField做缓存穿透兜底。它解决的是「学术模型如何扛住真实用户点击洪峰」这个工业级问题——适合正在写毕设/课设、但想避开“前端静态页后端假接口”套路的学生也适合中小厂想快速验证推荐策略、又没资源建独立 MLOps 平台的工程师。下面不讲原理图和公式推导直接拆解从零初始化一个能跑通端到端推荐流程的 Django 项目每一步命令为什么这么写、参数为什么这么设、哪里容易翻车全部摊开。2. 初始化 Django 项目并集成深度学习依赖避开 pip 依赖地狱的 3 个关键动作2.1 创建隔离环境并安装最小化 Django 栈不要用pip install django全局装尤其当你本地已装过多个版本的 PyTorch比如 1.12 和 2.0.1时Django 的asgiref、sqlparse会和torch的 C 运行时冲突导致python manage.py runserver启动时报ImportError: libtorch_cpu.so: cannot open shared object file。正确做法是用venvpip-tools锁定版本# 创建项目目录并进入 mkdir music-recommender cd music-recommender # 初始化虚拟环境Python 3.9 推荐兼容 PyTorch 2.x 和 Django 4.2 python -m venv venv source venv/bin/activate # Linux/macOS # venv\Scripts\activate.bat # Windows # 安装 pip-tools比 requirements.txt 更可靠 pip install pip-tools # 创建基础依赖文件注意不直接装 django 或 torch echo Django4.2,4.3 requirements.in echo djangorestframework3.14,3.15 requirements.in echo psycopg2-binary2.9.7 requirements.in echo celery5.3,5.4 requirements.in echo redis4.6,4.7 requirements.in echo numpy1.24,1.25 requirements.in echo pandas2.0,2.1 requirements.in echo scikit-learn1.3,1.4 requirements.in提示psycopg2-binary是 PostgreSQL 客户端驱动比源码编译版安装快且稳定celery5.3是当前最适配 Django 4.2 的版本低于 5.2 会因asyncio兼容性报错numpy1.25是为避坑 PyTorch 2.0.1 的 ABI 不兼容实测 1.25.0 导致torch.tensor构造失败。生成锁定文件并安装pip-compile requirements.in pip install -r requirements.txt验证 Django 是否可用django-admin startproject config . python manage.py migrate python manage.py createsuperuser python manage.py runserver此时访问http://127.0.0.1:8000/admin/应看到 Django 管理后台——说明基础栈已就位。2.2 安装 PyTorch 及音频处理库按 CUDA 版本精准匹配PyTorch 官网的pip install torch命令会默认装 CPU 版但你的推荐模型推理尤其是双塔模型的向量内积在 GPU 上快 5~8 倍。必须根据本机 CUDA 版本选包# 查看本机 CUDA 版本Linux/macOS nvcc --version # 输出类似Cuda compilation tools, release 11.8, V11.8.89 # 根据 CUDA 版本选 PyTorch以 CUDA 11.8 为例 pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118参数说明--index-url指向 CUDA 专用镜像比默认 PyPI 快 10 倍且避免下载中断torchaudio必装后续提取 MFCC、Mel-spectrogram 依赖其transforms.MFCC若无 GPU改用https://download.pytorch.org/whl/cpu但务必加--no-cache-dir防止 pip 缓存旧版导致torchaudio无法 import。接着装音频特征库pip install librosa0.10.1 # 注意0.10.2 有 librosa.feature.mfcc 返回维度 bug pip install soundfile0.12.1 # 比 scipy.io.wavfile 更稳定读取 24bit FLAC血泪经验librosa 0.10.1是最后一个兼容torch.stft输入torch.float32的版本新版librosa.feature.mfcc默认返回np.ndarray需手动转torch.tensor而0.10.1可直传torch.tensor给模型省去.numpy()→.tensor()的转换开销。2.3 创建推荐核心 App 并配置模型加载时机Django 的AppConfig.ready()是唯一安全的模型加载入口——它保证模型只在 Django 启动时加载一次且在所有模型类注册完成后执行避免AppRegistryNotReady错误python manage.py startapp recommender编辑recommender/apps.py# recommender/apps.py from django.apps import AppConfig import torch import os class RecommenderConfig(AppConfig): default_auto_field django.db.models.BigAutoField name recommender def ready(self): # 只在 Django 主进程加载模型避开 Celery worker 重复加载 if os.environ.get(RUN_MAIN) true: from .models import load_recommender_model load_recommender_model()在recommender/models.py中定义模型加载函数# recommender/models.py import torch from pathlib import Path _recommender_model None def load_recommender_model(): global _recommender_model model_path Path(__file__).parent / models / dual_tower_v2.pth if not model_path.exists(): raise FileNotFoundError(fModel not found at {model_path}) # 加载时指定 device避免后续推理时 device mismatch device torch.device(cuda if torch.cuda.is_available() else cpu) _recommender_model torch.jit.load(str(model_path), map_locationdevice) _recommender_model.eval() # 关键否则 dropout/batchnorm 影响推理 print(f[INFO] Recommender model loaded on {device}) def get_recommender_model(): global _recommender_model if _recommender_model is None: raise RuntimeError(Model not loaded. Call load_recommender_model() first.) return _recommender_model逻辑说明torch.jit.load()加载 TorchScript 模型比torch.load()快 30%且无需model.eval()外部调用map_locationdevice强制模型权重映射到当前设备防止CUDA error: invalid device ordinalglobal _recommender_model是单例模式确保整个 Django 进程共享同一模型实例内存占用降低 60%os.environ.get(RUN_MAIN) true过滤掉 Django 的 autoreload 子进程避免模型被加载两次。最后在config/settings.py中注册 App# config/settings.py INSTALLED_APPS [ django.contrib.admin, django.contrib.auth, django.contrib.contenttypes, django.contrib.sessions, django.contrib.messages, django.contrib.staticfiles, rest_framework, recommender, # ← 新增 ]执行python manage.py check应无错误——至此Django 已准备好承载深度学习模型。3. 设计音乐推荐数据模型从原始音频到可检索向量的 4 层结构3.1 用户行为表用GenericRelation支持多源行为归一化音乐推荐的核心不是歌曲本身而是用户与歌曲的交互。但用户行为来源多样Web 端播放完成、APP 端跳过、小程序端收藏、后台运营打标签……若为每种行为建一张表关联查询会爆炸。Django 的GenericForeignKey是解法# recommender/models.py from django.db import models from django.contrib.contenttypes.fields import GenericForeignKey from django.contrib.contenttypes.models import ContentType class UserAction(models.Model): 统一用户行为表支持播放、收藏、跳过、分享等 ACTION_TYPES ( (play, 播放), (skip, 跳过), (like, 喜欢), (share, 分享), (dislike, 不喜欢), ) user models.ForeignKey(auth.User, on_deletemodels.CASCADE) action_type models.CharField(max_length10, choicesACTION_TYPES) timestamp models.DateTimeField(auto_now_addTrue) # 泛型外键指向任意模型Song, Playlist, Album content_type models.ForeignKey(ContentType, on_deletemodels.CASCADE) object_id models.PositiveIntegerField() content_object GenericForeignKey(content_type, object_id) # 行为强度播放时长占比、收藏权重等 weight models.FloatField(default1.0) class Meta: ordering [-timestamp] indexes [ models.Index(fields[user, action_type]), models.Index(fields[content_type, object_id]), ]为什么不用ForeignKey到 Song因为推荐系统后期要接入「歌单相似推荐」「专辑冷启动推荐」泛型外键让UserAction表天然支持跨实体行为聚合无需修改表结构。content_type字段存Song的ContentType.idobject_id存具体Song.idDjango ORM 自动解析content_object为对应模型实例。3.2 歌曲元数据表用JSONField存储非结构化音频特征歌曲的文本元数据歌名、歌手、专辑用传统字段但 MFCC、Chroma、Tempo 等音频特征维度高MFCC 通常 13x128、更新频次低用关系型字段会撑爆表宽。PostgreSQL 的JSONField是最优解# recommender/models.py from django.contrib.postgres.fields import JSONField class Song(models.Model): title models.CharField(max_length200) artist models.CharField(max_length200) album models.CharField(max_length200, blankTrue) duration_ms models.IntegerField() # 音频特征存为 JSON结构示例 # { # mfcc: [0.12, -0.45, ..., 0.88], # shape(1664,) # chroma: [0.92, 0.33, ..., 0.11], # shape(12,) # tempo: 128.5, # spectral_centroid: 2340.1 # } audio_features JSONField(defaultdict) # 向量缓存用于近似最近邻搜索 embedding models.BinaryField(nullTrue, blankTrue) # 存 torch.float16 的 bytes created_at models.DateTimeField(auto_now_addTrue) def __str__(self): return f{self.title} - {self.artist} class Meta: indexes [ models.Index(fields[artist]), models.Index(fields[album]), ]参数说明JSONField(defaultdict)确保空值时存{}而非NULL避免json.loads(None)报错embedding用BinaryField存torch.float16的bytes比存float32节省 50% 存储且faiss库原生支持float16向量indexes为高频查询字段建索引artist和album查询频次远高于title用户常搜歌手或专辑名。3.3 用户画像表用ArrayField存储动态兴趣向量用户兴趣不是静态标签而是随时间衰减的向量。Django 的ArrayFieldPostgreSQL 扩展可存float[]配合django.contrib.postgres.indexes.GinIndex实现高效相似度计算# recommender/models.py from django.contrib.postgres.fields import ArrayField class UserProfile(models.Model): user models.OneToOneField(auth.User, on_deletemodels.CASCADE) # 兴趣向量双塔模型 User Tower 输出dim128 interest_vector ArrayField( models.FloatField(), size128, defaultlist, help_textUsers interest vector, updated daily ) # 最近活跃时间用于衰减计算 last_active models.DateTimeField(auto_nowTrue) # 兴趣标签从行为中提取的 Top-K 标签如 [jazz, lofi, chill] tags ArrayField( models.CharField(max_length50), size10, defaultlist ) def __str__(self): return fProfile for {self.user.username} class Meta: indexes [ # GinIndex 支持数组包含查询如 tags ARRAY[jazz] models.Index(fields[tags]), ]为什么不用TextField存 JSONArrayField支持原生数据库运算interest_vector (SELECT interest_vector FROM recommender_userprofile WHERE id123)可直接查相似用户而 JSON 字段需-解析后转数组性能差 5 倍以上。3.4 推荐结果缓存表用HStoreField实现多策略结果隔离不同推荐策略协同过滤、内容相似、热门榜结果格式不同但都要存、要过期、要 AB 测试。HStoreField键值对完美匹配# recommender/models.py from django.contrib.postgres.fields import HStoreField class RecommendationCache(models.Model): user models.ForeignKey(auth.User, on_deletemodels.CASCADE) strategy models.CharField( max_length20, choices[ (collab, 协同过滤), (content, 内容相似), (popularity, 热门榜), (hybrid, 混合策略), ] ) # 结果存为键值对{song_ids: [1,5,8,12], scores: [0.92,0.88,0.76,0.65]} results HStoreField() # 缓存过期时间分钟 ttl_minutes models.IntegerField(default60) created_at models.DateTimeField(auto_now_addTrue) def is_expired(self): from django.utils import timezone return (timezone.now() - self.created_at).total_seconds() self.ttl_minutes * 60 class Meta: unique_together (user, strategy) indexes [ models.Index(fields[user, strategy]), ]逻辑说明unique_together保证每个用户每种策略只存一份缓存避免重复计算is_expired()方法供视图层调用判断是否需重新生成推荐HStoreField在 PostgreSQL 中底层是hstore类型支持results - song_ids直接取值比JSONField的results - song_ids快 20%。4. 实现双塔模型推理服务从音频特征提取到向量召回的端到端链路4.1 音频特征提取 Pipeline用torchaudio替代librosa降耗librosa提取 MFCC 依赖numpy和scipyCPU 占用高torchaudio原生支持torch.Tensor可 GPU 加速# recommender/audio_processor.py import torch import torchaudio from torchaudio.transforms import MFCC, MelSpectrogram class AudioFeatureExtractor: def __init__(self, sample_rate22050, n_mfcc13, n_mels128): self.sample_rate sample_rate self.mfcc_transform MFCC( sample_ratesample_rate, n_mfccn_mfcc, melkwargs{n_mels: n_mels, n_fft: 2048, hop_length: 512} ) self.mel_spec_transform MelSpectrogram( sample_ratesample_rate, n_melsn_mels, n_fft2048, hop_length512 ) def extract_mfcc(self, waveform: torch.Tensor) - torch.Tensor: 输入 shape(1, T)输出 shape(n_mfcc, T//hop_length) mfcc self.mfcc_transform(waveform) return mfcc.flatten().float() # 展平为 1D tensor def extract_chroma(self, waveform: torch.Tensor) - torch.Tensor: Chroma 特征mel spectrogram 按 12 音阶折叠 mel_spec self.mel_spec_transform(waveform) # 简化版 Chroma取 log-mel-spec 的前 12 行实际应做音阶映射 chroma torch.mean(mel_spec[:12], dim1) return chroma.float() # 全局单例避免重复初始化 transform _extractor AudioFeatureExtractor() def extract_audio_features(waveform: torch.Tensor) - dict: return { mfcc: _extractor.extract_mfcc(waveform).tolist(), chroma: _extractor.extract_chroma(waveform).tolist(), tempo: 120.0, # 实际用 librosa.beat.tempo此处简化 spectral_centroid: 2340.1, }参数说明n_mfcc13是行业标准覆盖人耳敏感频段hop_length512对应 23ms 帧移平衡时频分辨率flatten().tolist()转为 Python list适配JSONField存储waveform必须是torch.Tensor类型为float32shape(1, T)单声道。4.2 双塔模型推理用torch.jit.trace优化延迟模型代码不放这里假设你已有训练好的DualTowerModel重点是部署时的torch.jit.trace# recommender/models.py import torch import torch.nn as nn class DualTowerModel(nn.Module): def __init__(self, user_dim64, item_dim128, hidden_dim256): super().__init__() self.user_tower nn.Sequential( nn.Linear(user_dim, hidden_dim), nn.ReLU(), nn.Linear(hidden_dim, 128) ) self.item_tower nn.Sequential( nn.Linear(item_dim, hidden_dim), nn.ReLU(), nn.Linear(hidden_dim, 128) ) def forward(self, user_feat: torch.Tensor, item_feat: torch.Tensor): user_vec self.user_tower(user_feat) item_vec self.item_tower(item_feat) return torch.cosine_similarity(user_vec, item_vec, dim1) # 导出 TorchScript 模型在训练脚本中执行 def export_model(): model DualTowerModel() model.eval() # 构造 dummy input必须和线上推理 shape 一致 dummy_user torch.randn(1, 64) # batch_size1, user_feat_dim64 dummy_item torch.randn(1, 128) # batch_size1, item_feat_dim128 traced_model torch.jit.trace(model, (dummy_user, dummy_item)) traced_model.save(recommender/models/dual_tower_v2.pth)为什么用trace不用scripttrace对简单前向网络无控制流、无动态 shape更稳定script需注释类型且if/for语句易出错。本项目双塔模型无条件分支trace足够。4.3 向量召回服务用 FAISS 实现毫秒级相似搜索get_recommender_model()返回的模型输出是用户向量需在歌曲向量库中找 Top-K 相似项。FAISS 是 Facebook 开源的高效向量检索库pip install faiss-cpu # CPU 版GPU 版需额外编译# recommender/vector_search.py import faiss import numpy as np import torch from django.core.cache import cache from recommender.models import Song class VectorSearchEngine: def __init__(self): self.index None self.song_ids [] def build_index(self): 从 Song 表构建 FAISS 索引每日定时任务触发 songs Song.objects.exclude(embedding__isnullTrue).values_list(id, embedding) if not songs: return # 将 BinaryField 的 bytes 转为 float16 numpy array embeddings [] self.song_ids [] for song_id, emb_bytes in songs: emb np.frombuffer(emb_bytes, dtypenp.float16) embeddings.append(emb.astype(np.float32)) # FAISS 需 float32 self.song_ids.append(song_id) if not embeddings: return embeddings np.stack(embeddings).astype(float32) self.index faiss.IndexFlatIP(embeddings.shape[1]) # 内积相似度 self.index.add(embeddings) def search(self, query_vector: np.ndarray, k10) - list: query_vector shape(128,)返回 [(song_id, score), ...] if self.index is None: self.build_index() # FAISS 要求 query 为 2D array D, I self.index.search(query_vector.reshape(1, -1), k) results [] for i in range(len(I[0])): song_id self.song_ids[I[0][i]] if I[0][i] len(self.song_ids) else None if song_id: results.append((song_id, float(D[0][i]))) return results # 全局单例 search_engine VectorSearchEngine()关键参数IndexFlatIP是精确内积搜索比IndexIVFFlat更准推荐场景不能容忍近似误差query_vector.reshape(1, -1)强制 2DFAISS 不接受 1D 输入cache未使用因search_engine是模块级变量build_index()只在首次search()时触发后续复用内存索引。4.4 推荐视图用 Django REST Framework 封装推理链路# recommender/views.py from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import status from django.contrib.auth.models import User from recommender.models import RecommendationCache, UserProfile, Song from recommender.vector_search import search_engine from recommender.models import get_recommender_model class RecommendView(APIView): def get(self, request): user request.user if not user.is_authenticated: return Response({error: Authentication required}, statusstatus.HTTP_401_UNAUTHORIZED) # 1. 检查缓存 cache_obj RecommendationCache.objects.filter( useruser, strategyhybrid ).first() if cache_obj and not cache_obj.is_expired(): return Response({ recommendations: cache_obj.results, cached: True }) # 2. 获取用户画像向量 try: profile UserProfile.objects.get(useruser) if not profile.interest_vector: raise ValueError(User profile vector not computed) user_vector np.array(profile.interest_vector, dtypenp.float32) except (UserProfile.DoesNotExist, ValueError) as e: return Response({error: str(e)}, statusstatus.HTTP_400_BAD_REQUEST) # 3. FAISS 搜索 try: song_scores search_engine.search(user_vector, k20) except Exception as e: return Response({error: fSearch failed: {e}}, statusstatus.HTTP_500_INTERNAL_SERVER_ERROR) # 4. 构建结果含歌曲元数据 recommendations [] for song_id, score in song_scores: try: song Song.objects.get(idsong_id) recommendations.append({ id: song.id, title: song.title, artist: song.artist, score: round(score, 4), duration_ms: song.duration_ms }) except Song.DoesNotExist: continue # 5. 缓存结果异步避免阻塞响应 RecommendationCache.objects.update_or_create( useruser, strategyhybrid, defaults{ results: { song_ids: [r[id] for r in recommendations], scores: [r[score] for r in recommendations], titles: [r[title] for r in recommendations] }, ttl_minutes: 60 } ) return Response({ recommendations: recommendations, cached: False }) # urls.py from django.urls import path from recommender import views urlpatterns [ path(api/recommend/, views.RecommendView.as_view(), namerecommend), ]逻辑说明get()方法先查缓存命中则秒回未命中才走完整链路search_engine.search()返回(song_id, score)元组再查Song表补全元数据避免Song表字段冗余到RecommendationCacheupdate_or_create()保证缓存原子性defaults参数自动处理创建/更新缓存ttl_minutes60是经验值用户兴趣变化周期约 1 小时太短增加计算压力太长推荐陈旧。5. 避坑指南Django 深度学习项目上线前必踩的 4 个坑5.1 现象torch.load()报OSError: [Errno 2] No such file or directory原因模型文件路径在 Django 中是相对路径manage.py启动时工作目录是项目根目录但celery worker启动时工作目录可能是/home/user导致Path(__file__).parent / models解析错误。解决用settings.BASE_DIR绝对路径# recommender/models.py from django.conf import settings model_path settings.BASE_DIR / recommender / models / dual_tower_v2.pth并在config/settings.py中定义import os from pathlib import Path BASE_DIR Path(__file__).resolve().parent.parent.parent5.2 现象UserAction泛型外键查询极慢content_object访问耗时 2s原因Django 默认对每个content_object发起一次数据库查询N1 问题10 条行为记录就要查 10 次Song表。解决用prefetch_related预加载# 视图中 actions UserAction.objects.filter(userrequest.user).prefetch_related( content_object ) # 但需自定义 prefetch因 GenericForeignKey 不支持直接 prefetch # 正确做法用 django.contrib.contenttypes.generic.GenericRelation # 已在 3.1 节模型中体现此处为补充说明5.3 现象FAISS IndexFlatIP搜索返回score 1.0或负数原因FAISS 的IndexFlatIP计算的是内积dot product不是余弦相似度cosine similarity。当向量未归一化时内积范围是[-||u||*||v||, ||u||*||v||]非[-1,1]。解决在构建索引前归一化向量# vector_search.py embeddings np.stack(embeddings).astype(float32) # 归一化 embeddings embeddings / np.linalg.norm(embeddings, axis1, keepdimsTrue) self.index faiss.IndexFlatIP(embeddings.shape[1]) self.index.add(embeddings)同时用户向量query_vector也要归一化query_vector query_vector / np.linalg.norm(query_vector)5.4 现象Django Admin 中Song.audio_features显示JSONField乱码原因JSONField在 Admin 中默认用TextField渲染不支持 JSON 格式化。解决自定义 Admin# recommender/admin.py from django.contrib import admin from django.forms import Textarea from django.db import models from .models import Song admin.register(Song) class SongAdmin(admin.ModelAdmin): list_display [title, artist, duration_ms] formfield_overrides { models.JSONField: {widget: Textarea(attrs{rows: 4, cols: 40})}, }提示生产环境建议用django-json-widget第三方包支持折叠/高亮。6. 进阶技巧用 Celery Beat 实现用户画像向量的每日自动更新推荐效果衰减的核心是用户兴趣漂移。不能等用户点开 APP 才计算向量必须后台定时更新。Django 自带的cron不够灵活Celery Beat 是工业级方案。6.1 配置 Celery 和 Beat# 安装 pip install celery[redis] # 创建 celery.py同 manage.py 平级 # celery.py import os from celery import Celery os.environ.setdefault(DJANGO_SETTINGS_MODULE, config.settings) app Celery(config) app.config_from_object(django.conf:settings, namespaceCELERY) app.autodiscover_tasks()在config/settings.py中添加# config/settings.py CELERY_BROKER_URL redis://127.0.0.1:6379/0 CELERY_RESULT_BACKEND redis://127.0.0.1:6379/0 CELERY_BEAT_SCHEDULE { update-user-profiles-daily: { task: recommender.tasks.update_user_profiles, schedule: 3600.0, # 每小时检查一次实际每天执行一次 }, } CELERY_TIMEZONE Asia/Shanghai6.2 编写用户向量更新任务# recommender/tasks.py from celery import shared_task from django.contrib.auth.models import User from recommender.models import UserProfile, Song, UserAction from recommender.vector_search import search_engine import numpy as np shared_task def update_user_profiles(): 每日更新所有活跃用户的兴趣向量 # 只更新过去 7 天有行为的用户 from django.utils import timezone seven_days_ago timezone.now() p a hrefhttps://download.csdn.net/download/qq_33037637/88158220 stylecolor:#ec7500;font-size:14px; 本文还有配套的精品资源点击获取 /a img altmenu-r.4af5f7ec.gif srchttps://csdnimg.cn/release/wenkucmsfe/public/img/menu-r.4af5f7ec.gif stylewidth:16px;margin-left:4px;vertical-align:text-bottom;cursor:text; /p