

前言
就在昨晚,DeepSeek v3推出了新版本V3-0324,再次一夜爆火。
虽然官方表示"这只是一次小升级""API接口和使用方式不变",但经过Zilliz的第一时间实测,我们发现无论是逻辑能力,还是编程能力,相较原本的v3,都有了极大提升,甚至可以说,这是目前市面上最顶级的开源非推理模型。
具体来说,改变有以下三点:
参数量上,V3-0324为6850亿,较上一版本的6710亿略有提升;
上下文窗口上,V3-0324升级到了 128k
能力上,V3-0324的代码、数学、逻辑等能力有了较大提升。
整个V3的设计依然延用了V2提出的MLA(Multi-head Latent Attention)架构,既多头潜在注意力机制,通过潜在向量(latent vector)对Key-Value(KV)缓存进行压缩,从而减少推理时的内存占用和计算开销。
此外DeepSeek V3将除前三层外的所有 FFN 层替换为 MoE 层,每个MoE 层包含 1 个共享专家和 256 个路由专家。在路由专家中,每个 token 将激活 评分靠前的几个专家,以平衡整体的计算量。
另外,围绕准确率的提升,DeepSeek V3还使用了多token预测(MTP),通过多层级联预测机制,打破了传统模型只能一次多预测一个token的限制,让每个 token同时预测多个未来token,进而提升模型性能和数据效率。
那么DeepSeek v3-0324该如何用?企业场景应该如何部署?如何将它与RAG结合?本篇文章,我们会对DeepSeek v3的亮点进行梳理,并对其RAG搭建流程与效果,做一个简单的示例。
01
使用Milvus和DeepSeek搭建RAG
接下来,我们将展示如何使用Milvus和DeepSeek构建检索增强生成(RAG)pipeline。
步骤一:准备
(1)依赖和环境
sql
! pip install --upgrade "pymilvus[model]" openai requests tqdm
如果您使用的是Google Colab,要启用刚刚安装的依赖项,您可能需要重启运行环境(单击屏幕顶部的"Runtime"菜单,然后从下拉框中选择"Restart session")。
(2)准备数据
我们使用Milvus文档2.4. x中的FAQ页面作为RAG中的私有知识,这是搭建一个入门RAG pipeline的优质数据源。
首先,下载zip文件并将文档解压缩到文件夹milvus_docs。
diff
! wget https://github.com/milvus-io/milvus-docs/releases/download/v2.4.6-preview/milvus_docs_2.4.x_en.zip
! unzip -q milvus_docs_2.4.x_en.zip -d milvus_docs
我们从文件夹milvus_docs/en/faq中加载所有markdown文件,对于每个文档,我们只需简单地使用"#"来分隔文件中的内容,就可以大致分隔markdown文件各个主要部分的内容。
python
from glob import glob
text_lines = []
for file_path in glob("milvus_docs/en/faq/*.md", recursive=True):
with open(file_path, "r") as file:
file_text = file.read()
text_lines += file_text.split("# ")
(3)准备LLM和embedding模型
OpenRouter是一家提供统一API接口聚合多个主流AI模型(如DeepSeek、Claude等)的服务平台,让开发者通过单一接入点调用不同大语言模型。在OpenRouter上免费创建DeepSeek V3的API秘钥就可以尝鲜使用DeepSeek V3 0324。(其他平台操作同理,目前仅OpenRouter上线了最新版V3)

javascript
from openai import OpenAI
deepseek_client = OpenAI(
api_key="<OPENROUTER_API_KEY>",
base_url="https://openrouter.ai/api/v1",
)
选择一个embedding模型,使用milvus_model来做文本向量化。我们以DefaultEmbeddingFunction模型为例,它是一个预训练的轻量级embedding模型。
javascript
from pymilvus import model as milvus_model
embedding_model = milvus_model.DefaultEmbeddingFunction()
生成测试向量,并输出向量维度以及测试向量的前几个元素。
makefile
test_embedding = embedding_model.encode_queries(["This is a test"])[0]
embedding_dim = len(test_embedding)
print(embedding_dim)
print(test_embedding[:10])
json
768
[-0.04836066 0.07163023 -0.01130064 -0.03789345 -0.03320649 -0.01318448
-0.03041712 -0.02269499 -0.02317863 -0.00426028]
步骤二:将数据加载到Milvus
创建集合
makefile
from pymilvus import MilvusClient
milvus_client = MilvusClient(uri="./milvus_demo.db")
collection_name = "my_rag_collection"
对于MilvusClient需要说明:
将uri设置为本地文件,例如./milvus. db,是最方便的方法,因为它会自动使用Milvus Lite将所有数据存储在此文件中。
如果你有大规模数据,你可以在docker或kubernetes上设置一个更高性能的Milvus服务器。在此设置中,请使用服务器uri,例如http://localhost:19530,作为你的uri。
如果要使用Milvus的全托管云服务Zilliz Cloud,请调整uri和token,分别对应Zilliz Cloud中的Public Endpoint和Api密钥。
检查集合是否已经存在,如果存在则将其删除。
css
if milvus_client.has_collection(collection_name):
milvus_client.drop_collection(collection_name)
使用指定的参数创建一个新集合。
如果我们不指定任何字段信息,Milvus将自动为主键创建一个默认的id字段,并创建一个向量字段来存储向量数据。保留的JSON字段用于存储未在schema里定义的标量数据。
bash
milvus_client.create_collection(
collection_name=collection_name,
dimension=embedding_dim,
metric_type="IP", # Inner product distance
consistency_level="Strong", # Strong consistency level
)
插入数据
逐条取出文本数据,创建嵌入,然后将数据插入Milvus。
这里有一个新的字段"text",它是集合schema中的非定义字段,会自动添加到保留的JSON动态字段中。
kotlin
from tqdm import tqdm
data = []
doc_embeddings = embedding_model.encode_documents(text_lines)
for i, line in enumerate(tqdm(text_lines, desc="Creating embeddings")):
data.append({"id": i, "vector": doc_embeddings[i], "text": line})
milvus_client.insert(collection_name=collection_name, data=data)
ruby
Creating embeddings: 100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 72/72 [00:00<00:00, 1222631.13it/s]
{'insert_count': 72, 'ids': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71], 'cost': 0}
go
步骤三:构建RAG
检索查询数据
让我们指定一个关于Milvus的常见问题。
ini
question = "How is data stored in milvus?"
go
在集合中搜索问题并检索语义top-3匹配项。
makefile
search_res = milvus_client.search(
collection_name=collection_name,
data=embedding_model.encode_queries(
[question]
), # Convert the question to an embedding vector
limit=3, # Return top 3 results
search_params={"metric_type": "IP", "params": {}}, # Inner product distance
output_fields=["text"], # Return the text field
)
我们来看一下query的搜索结果
swift
import json
retrieved_lines_with_distances = [
(res["entity"]["text"], res["distance"]) for res in search_res[0]
]
print(json.dumps(retrieved_lines_with_distances, indent=4))
sql
[
[
" Where does Milvus store data?\n\nMilvus deals with two types of data, inserted data and metadata. \n\nInserted data, including vector data, scalar data, and collection-specific schema, are stored in persistent storage as incremental log. Milvus supports multiple object storage backends, including [MinIO](https://min.io/), [AWS S3](https://aws.amazon.com/s3/?nc1=h_ls), [Google Cloud Storage](https://cloud.google.com/storage?hl=en#object-storage-for-companies-of-all-sizes) (GCS), [Azure Blob Storage](https://azure.microsoft.com/en-us/products/storage/blobs), [Alibaba Cloud OSS](https://www.alibabacloud.com/product/object-storage-service), and [Tencent Cloud Object Storage](https://www.tencentcloud.com/products/cos) (COS).\n\nMetadata are generated within Milvus. Each Milvus module has its own metadata that are stored in etcd.\n\n###",
0.6572665572166443
],
[
"How does Milvus flush data?\n\nMilvus returns success when inserted data are loaded to the message queue. However, the data are not yet flushed to the disk. Then Milvus' data node writes the data in the message queue to persistent storage as incremental logs. If `flush()` is called, the data node is forced to write all data in the message queue to persistent storage immediately.\n\n###",
0.6312146186828613
],
[
"How does Milvus handle vector data types and precision?\n\nMilvus supports Binary, Float32, Float16, and BFloat16 vector types.\n\n- Binary vectors: Store binary data as sequences of 0s and 1s, used in image processing and information retrieval.\n- Float32 vectors: Default storage with a precision of about 7 decimal digits. Even Float64 values are stored with Float32 precision, leading to potential precision loss upon retrieval.\n- Float16 and BFloat16 vectors: Offer reduced precision and memory usage. Float16 is suitable for applications with limited bandwidth and storage, while BFloat16 balances range and efficiency, commonly used in deep learning to reduce computational requirements without significantly impacting accuracy.\n\n###",
0.6115777492523193
]
]
使用LLM获取RAG响应
将检索到的文档转换为字符串格式。
cs
context = "\n".join(
[line_with_distance[0] for line_with_distance in retrieved_lines_with_distances]
)
为LLM定义系统和用户提示。这个提示是由从Milvus检索到的文档组装而成的。
ini
SYSTEM_PROMPT = """
Human: You are an AI assistant. You are able to find answers to the questions from the contextual passage snippets provided.
"""
USER_PROMPT = f"""
Use the following pieces of information enclosed in <context> tags to provide an answer to the question enclosed in <question> tags.
<context>
{context}
</context>
<question>
{question}
</question>
"""
使用DeepSeek提供的deepseek/deepseek-chat-v3-0324模型根据提示生成响应。
makefile
response = deepseek_client.chat.completions.create(
model="deepseek/deepseek-chat-v3-0324",
messages=[
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": USER_PROMPT},
],
)
print(response.choices[0].message.content)
kotlin
Milvus stores data in two main categories: inserted data and metadata.
1. **Inserted Data**:
- This includes vector data, scalar data, and collection-specific schema.
- The data is stored in persistent storage as incremental logs.
- Milvus supports various object storage backends for this purpose, such as MinIO, AWS S3, Google Cloud Storage (GCS), Azure Blob Storage, Alibaba Cloud OSS, and Tencent Cloud Object Storage (COS).
2. **Metadata**:
- Metadata is generated internally by Milvus and is specific to each module.
- This metadata is stored in etcd.
For vector data, Milvus supports multiple types including Binary, Float32, Float16, and BFloat16, each with different precision and use cases. The data is initially loaded into a message queue upon insertion and is later written to persistent storage by the data node, either during regular operations or immediately if `flush()` is called.
go
至此,通过Milvus和DeepSeek构建了一个RAG pipeline的完整流程正式完成。
02
对比:原装版DeepSeek-V3-0324 VS RAG版
在搭建好一个最基本的RAG之后,接下来,我们对原装版DeepSeek-V3-0324 以及结合了Milvus+DeepSeek-V3-0324的RAG版本做一下效果对比。
对比问题可以选用"write HTML code to create a fancy website about Milvus"。
我们直接在官网的对话框关闭【深度思考】,然后直接提问,效果如下:

下面是集成了Milvus的RAG版本,将上文代码中的question进行替换
ini
question="write HTML code to create a fancy website about Milvus"
生成的网站如下:

通过对比我们可以看到,在整体审美风格比较接近的情况下,RAG版网站,无论是产品简介,还是具体的亮点分析,都更加符合实际的Milvus特性。建立在本地文档所提供的更丰富的语料语料基础上,给出的整体网站内容也会更加丰富、专业,不空洞。
03
写在最后
其实不只是代码能力,在数学推理、长文本阅读推理等方面,新版V3均有较大程度的提升,几乎与Claude 3.7 Sonnet 媲美。
另外,我们通过实验发现,相比前一段时间风很大的推理模型,作为非推理模型的新版V3,虽然不会在回答中给出详细的推理过程,但其答案生成仍展现了一定的逻辑与思考能力。
与之形成对比,推理模型做RAG与Agent ,效果很好,但却会对一些简单的指令判断,做一大堆分析与反复思考确认,不仅消耗过多token,回答速度还慢。
而新版V3,对于一些成本敏感的场景来说,或许带来了问题的新解法。
更进一步,这也印证了诸如 OpenAI 的大模型厂商,后续不再区别推理和非推理模型背后的逻辑,模型服务应该自动根据需求判断是否推理,以节省不必要的 token 开销。
作者介绍

王舒虹
Zilliz Social Media Advocate
推荐阅读