1-Chroma-起步

系列文章目录

1-Chroma-起步



概述

Chroma是一款流行的开源嵌入(embedding)数据库。Chroma通过将知识、事实和技能等可插拔(pluggable)到 LLM(大语言模型)中,从而使得构建 LLM 应用变得很容易。这里需要说明的是:
(1)什么是嵌入(embed和embedding)?可以理解成将数据嵌入到向量里,想象有一个布满格子的模具,这些格子被排列成一行,现在将一个橡皮泥材质的小猫摁入(embed)到模具中,小猫就变成了模具的形状,这个塑形的过程就是嵌入,小猫代表一条数据,每个格子代表小猫的一个特征,一排格子就是一个特征向量,一个特征向量就被称为一个embedding,嵌入的本质就是将数据表示为特征向量,即数据向量化,这里的数据包括但不限于:单词,句子,段落,文章,公式,图片,语音,视频等任何可在计算机中表示的事物。
(2)什么是可插拔(pluggable)?经过Chroma处理或存储的数据可以做为上下文发送给 LLM,并被LLM识别,这些数据一旦存储后就可以被重复使用。
Chrome与App,LLM通常会被搭配使用,它们之间的配合流程如下图,该图摘自Chrome官网。首先App会将查询内容(一般是用户的提出的问题)发送给Chroma,Chroma查找与查询内容最相似的文档内容,App将查找的文档内容与查询内容一起作为LLM的上下文窗口(context window)发送给LLM,LLM回答问题并返回给App。
实际开发中,大多会与LangChain结合使用,LangChain对Chroma进行了集成封装,具体结合方式可以查看这个demo:https://github.com/hwchase17/chroma-langchain在这里插入图片描述
Chroma是基于CPU的,默认使用all-MiniLM-L6-v2嵌入模型,可以将嵌入模型更换为支持GPU的模型来支持GPU,能在Chroma中使用的支持GPU的模型包括:hkunlp/instructor-base,hkunlp/instructor-large和hkunlp/instructor-xl。
Chroma提供了以下工具:

  • 存储嵌入和它们的元数据
  • 嵌入文档和查询嵌入
  • 搜索嵌入
    Chroma的优势在于:
  • 简单,提高了开发者的生产率,API较少,调用容易,上手快,且足够灵活,能满足各种场景
  • 在搜索基础上提供了分析和处理功能,比如:where筛选,计数等
  • 具有快速的数据存储和查询能力,可以在短时间内处理大规模的向量数据
  • 被集成到了LangChain中,可以快速构建基于Chroma的AI应用

参考资料

官网主页:https://www.trychroma.com/
官网文档:https://docs.trychroma.com/
github主页:https://github.com/chroma-core/
github项目:https://github.com/chroma-core/chroma/

版本发布

Chroma是一个比较新的项目,通过github的可以看到,在2022-10-16创建了第一个版本0.0.1,2022-10-23发布了第一个预发布版本0.0.2,2023-07-18发布了第一个正式发布版本0.4.0,此后每次发布基本上都是正式发布,鲜有预发布。Chrome的迭代速度很快,平均下来几乎每周都会有发布,有时会密集发布。需要注意的是,预发布的版本通常未经过充分测试和验证,可能存在不稳定性或不完全符合预期的行为。

架构

Chroma采用C/S(Client/Server)架构模式,包括三部分:Python客户端SDK,JavaScript/TypeScript客户端SDK和服务端应用,服务端应用是基于Python的。开发者可以通过使用这三种编程语言去调用Chroma的服务端查询或存储数据。
Chroma提供了两种运行模式:in-memory和client/server,即内存模式和C/S模式。两者的区别在于是否通过url和端口号访问服务端,C/S模式可以请求其它机器上部署的Chroma服务端的服务,而in-memory则只能调用本地的Chroma服务端的服务。对于Python的C/S模式尚处于alpha开发阶段。
对于in-memory,也分成两种模式:ephemeral和persistent,即短暂模式和持久化模式。短暂模式下程序一旦结束数据就被销毁,持久化模式下数据会被存储到本地硬盘文件中供以后重复使用,再次启动程序会自动加载数据,关闭程序会自动保存数据。
不同的编程语言支持的模式不同,具体如下表格,该表格摘自官网。可以看出,Python同时支持两种模式,JavaScript仅支持客户端,而其它语言需要借助中间件才能使用客户端。

in-memoryclient
Python✅(by Chroma)
Javascript✅ (by Chroma)
Rubyfrom @mariochavez
Javafrom @t_azarov
Gofrom @t_azarov
C#from @microsoft
Rustfrom @Anush008
Elixirfrom @3zcurdia
Dartfrom @davidmigloz
Other?

开发和运行环境

以下安装和示例程序都是针对Python编程,在win10的conda虚拟环境中运行过,chromadb被安装在conda虚拟环境中。

包安装

如果网速不快,可以使用清华源。

pip install chromadb -i https://pypi.tuna.tsinghua.edu.cn/simple

编码流程及示例

这里只演示in-memory的ephemeral模式,该模式仅支持Python,对于其它模式请关注后续文章。in-memory模式的编码流程包含四步:

1.获取客户端 > 2.创建或获取被查询集合 > 3.往集合中添加被查询数据 > 4.查询集合中的数据

在ephemeral模式下数据并没有持久化到硬盘中,程序运行结束数据就会销毁。如果要持久化,则需要在Client()中设置setting参数,或使用PersistentClient(path)创建客户端(Chroma的版本要大于0.4.0),将数据保存到指定的文件中。持久化后,collection可以被重复使用,之后再次启动客户端,会自动加载collection的数据,若添加数据,关闭客户端会自动保存。持久化会放到后续文章介绍。

步骤1:获取客户端

import chromadb
# in-memory ephemeral model
client = chromadb.Client()

如果Chroma版本大于0.4.0,可以这样调用。

import chromadb
# in-memory ephemeral model
client = chromadb.EphemeralClient()

步骤2:创建或获取被查询集合

集合是一个用来存放嵌入,文档和元数据的容器。允许同时创建多个集合,集合名称是必须的,用来区分多个不同的集合,且名称长度限制在3-63个字符之间,还有一些其他限制,后续文章会详细介绍。存贮在集合中的数据会提供给用户进行查询。嵌入即特征向量,文档即文本内容,元数据是用来描述文档的属性,包括:名称,来源,类型,作者等自定义属性,具体可以参考第三步的添加数据。

collection = client.create_collection(name="my_collection")

对于已存在的集合,可以直接通过名称获取,如果集合不存在会报错。

collection = client.get_collection(name="my_collection")

也可以通过以下方式调用,如果给定名称的集合已经存在则直接获取,否则创建。

collection = client.get_or_create_collection(name="my_collection")

步骤3:往集合中添加被查询数据

添加被查询数据后,就可以通过查询方法找出与用户输入信息最相近的数据。add方法的参数有:

  1. ids:多个文档的唯一标识列表,必传参数。
  2. embeddings:多个文档的嵌入列表,嵌入也是数组,选传参数,但是与documents参数至少有一个要传。
  3. documents:多个文档的文本内容字符串列表,选传参数,但是与embeddings参数至少有一个要传。
  4. metadatas:多个文档的元数据字典列表,元数据的数据可以是任何自定义文档属性,包括:名称,来源,类型,作者等。

这四个参数都是列表,且长度要一致,有几个文档就要有几个元素。
如果传入的是文档的内容文本,Chroma会自动处理分词(tokenization),嵌入(embedding)和索引(indexing),后续的查询方法需要使用query_texts参数。

collection.add(
    ids=["id1", "id2", "id3", "id4", "id5"],
    documents=["浙江的省会是杭州", "河北的省会是石家庄", "山东的省会是济南", "杭州是个美丽的城市", "杭州位于浙江省"],
    metadatas=[{"source": "myDoc"}, {"source": "myDoc"}, {"source": "myDoc"}, {"source": "myDoc"}, {"source": "myDoc"}],
)

如果已经有生成好的嵌入,可以通过embeddings参数直接传入,后续的查询方法需要使用query_embeddings参数。

collection.add(
    ids=["id1", "id2", "id3", "id4", "id5"],
    # 注意如果使用了embedings参数,且嵌入维度不是384(当前是3),则第四步中的查询需要使用query_embeddings传参查询
    # 其余情况,可以使用query_texts传参查询
    embeddings=[[1.2, 2.3, 4.5], [3.3, 5.1, 2.7], [6.1, 8.2, 9.2], [1.8, 0.2, 2.1], [5.5, 6.6, 9.9]],
    documents=["浙江的省会是杭州", "河北的省会是石家庄", "山东的省会是济南", "杭州是个美丽的城市", "杭州位于浙江省"],
    metadatas=[{"source": "myDoc"}, {"source": "myDoc"}, {"source": "myDoc"}, {"source": "myDoc"}, {"source": "myDoc"}],
)

步骤4:查询集合中的数据

查询集合中与用户给定的文本或嵌入(特征向量)最相似的n个文档,n由用户指定,这n条文档会按照相似度从高到低排列被返回。这里用到的查询策略不是常规的模式匹配,而是采用相似度(K-近邻算法),相似度愈高,返回数据中的距离(distance)值越小,如果值为0,表明内容一模一样。query方法的参数有:

  1. query_texts:查询文本列表
  2. query_embeddings:查询嵌入列表
  3. n_results:与每个查询文本或嵌入最相近的文档数
results = collection.query(
    query_texts=["西湖在浙江杭州"],
    n_results=5,
)
# 运行结果如下:
{'ids': [['id5', 'id4', 'id1', 'id3', 'id2']], 'distances': [[0.43458253145217896, 0.48921626806259155, 0.5748544931411743, 0.9643734097480774, 1.0526437759399414]], 'metadatas': [[{'source': 'myDoc'}, {'source': 'myDoc'}, {'source': 'myDoc'}, {'source': 'myDoc'}, {'source': 'myDoc'}]], 'embeddings': None, 'documents': [['杭州位于浙江省', '杭州是个美丽的城市', '浙江的省会是杭州', '山东的省会是济南', '河北的省会是石家庄']]}
<think>好的,用户希望作为个人用户,将DeepSeek打造成自己的全方位助手,需要全量模型,并且有一定的本地化数据库扩展和定制能力。之前已经讨论过本地部署和API调用的区别,现在用户具体想了解如何实施。 首先,用户的需求是个人使用,可能资源有限,比如硬件和预算。需要确认用户是否有足够的本地计算资源,比如GPU,或者是否需要依赖云服务。全量模型可能指的是完整的模型参数,本地部署可能需要较高的硬件配置。 接下来,本地化数据库扩展,意味着用户希望模型能够访问自己的私有数据,比如文档、笔记等。这里可能需要RAG(检索增强生成)技术,或者微调模型。但微调需要技术和数据准备,而RAG相对容易实现。 定制能力和处理习惯,用户可能需要模型按照特定的方式回答问题,或者集成到自己的工作流程中。可能需要结合外部脚本或工具,对输入输出进行处理,或者设置特定的提示模板。 用户可能没有提到但需要考虑的点包括数据隐私、成本、维护难度。作为个人用户,可能更倾向于低成本、易维护的方案,比如使用API结合本地数据库,而不是完全本地部署大模型。 需要分步骤建议,可能包括数据准备、模型选择(本地还是API)、扩展方法(RAG或微调)、集成工具等。同时,考虑到用户是个人,可能需要推荐一些开源工具或框架,降低技术门槛。 最后,提醒可能的挑战,比如硬件要求高,技术复杂度,时间成本,并给出实用建议,比如从简单开始逐步优化。</think>作为个人用户,若想将DeepSeek打造成符合自身需求的**全方位助手**,需要结合本地化数据扩展、个性化定制和技术工具链的搭建。以下是具体实现路径和关键步骤: --- ### **一、核心能力需求拆解** 根据你的描述,需要实现三个核心目标: 1. **全量模型掌控**:使用完整模型参数(非精简版),最大化模型能力 2. **本地化数据扩展**:让模型理解你的私有知识库(如个人笔记、专业资料等) 3. **个性化定制**:适配你的语言风格、任务处理习惯和特定工作流 --- ### **二、实现方案设计** #### **1. 模型部署选择** | **方案** | **优势** | **挑战** | **推荐度** | |----|----------------------------------|----------| | **本地部署全量模型** | 完全控制模型和数据隐私 | 需要高性能GPU(如RTX 3090/4090) | ★★★★☆ | | **云端API+本地增强** | 低成本起步,适合轻量级需求 | 依赖网络,数据需加密传输 | ★★★☆☆ | | **混合架构** | 平衡性能与成本(关键任务本地+通用任务API) | 架构复杂度较高 | ★★☆☆☆ | **建议**:若拥有至少24GB显存的GPU(可运行13B~34B参数模型),优先选择**本地部署**;否则从**API调用+RAG增强**起步--- ### **三、关键实施步骤** #### **阶段1:基础环境搭建** 1. **硬件准备** - **最低配置**:NVIDIA RTX 3090(24GB显存) + 32GB内存 - **推荐配置**:双卡RTX 4090(48GB显存) + 64GB内存(可运行70B参数模型) - **存储**:至少500GB SSD用于存储模型和知识库 2. **模型获取与部署** - 从DeepSeek官方获取全量模型(如`deepseek-llm-67b-chat`) - 使用**vLLM**或**llama.cpp**部署推理服务(优化显存和吞吐量) ```bash # 示例:使用vLLM启动API服务 python -m vllm.entrypoints.api_server --model deepseek-ai/deepseek-llm-67b-chat --tensor-parallel-size 2 ``` #### **阶段2:本地知识库扩展** 1. **数据准备** - 结构化个人数据:整理笔记/邮件/文档为Markdown或JSON格式 - 非结构化数据:用`unstructured`库解析PDF/PPT/网页内容 ```python from unstructured.partition.pdf import partition_pdf elements = partition_pdf("my_notes.pdf") ``` 2. **构建检索增强系统(RAG)** - 使用**ChromaDB**或**FAISS**建立向量数据库 - 用`text-embedding-3-small`生成知识库嵌入向量 ```python from langchain_community.vectorstores import Chroma from langchain_openai import OpenAIEmbeddings vectorstore = Chroma.from_documents( documents=your_docs, embedding=OpenAIEmbeddings(model="text-embedding-3-small") ) ``` 3. **与模型集成** - 通过LangChain实现RAG管道 ```python from langchain.chains import RetrievalQA from langchain_community.llms import VLLMOpenAI llm = VLLMOpenAI( openai_api_base="http://localhost:8000/v1", model_name="deepseek-67b-chat", max_tokens=2048 ) qa_chain = RetrievalQA.from_chain_type( llm=llm, retriever=vectorstore.as_retriever(), chain_type="stuff" ) ``` #### **阶段3:个性化定制** 1. **提示词工程** - 在系统提示中定义角色和响应规则 ```python SYSTEM_PROMPT = """你是一个高度定制化的个人助手,遵循以下规则: 1. 使用简洁的技术文档风格回复 2. 优先引用用户知识库中的内容 3. 拒绝讨论与用户专业领域无关的话题""" ``` 2. **微调模型(进阶)** - 使用LoRA在私有数据上微调(需16GB+显存) ```python from peft import LoraConfig peft_config = LoraConfig( r=8, lora_alpha=32, target_modules=["q_proj", "v_proj"], lora_dropout=0.05, bias="none" ) ``` 3. **习惯捕捉自动化** - 用**Loguru**记录交互历史,分析高频需求 - 通过`langsmith`监控并优化任务处理流程 --- ### **四、典型应用场景实现** #### **场景1:个人知识管理** - **输入**:`检索我2023年关于RAG的笔记,总结成思维导图` - **流程**: 1. RAG检索相关文档片段 2. 调用`graphviz`生成可视化导图 3. 自动保存到指定目录 #### **场景2:自动化工作流** - **输入**:`监控我的GitHub项目,每日用中文生成开发进度简报` - **实现**: ```python def generate_daily_report(): issues = get_github_issues() report_prompt = f"用简洁的列表总结以下问题:\n{issues}" return qa_chain.invoke(report_prompt) schedule.every().day.at("09:00").do(generate_daily_report) ``` --- ### **五、成本与效率优化建议** 1. **硬件节省方案** - 使用**GGUF量化**(如Q4_K_M)降低显存占用 ```bash ./llama.cpp/quantize deepseek-67b-f16.gguf deepseek-67b-q4_k.gguf Q4_K_M ``` 2. **计算资源复用** - 通过**Ollama**同时运行多个量化模型 3. **API替代方案** - 对实时性要求低的任务使用DeepSeek API(成本约$0.1/千token) --- ### **六、注意事项** 1. **数据安全** - 本地部署时启用磁盘加密(如LUKS) - API调用时使用`cryptography`库加密传输数据 2. **可持续维护** - 建立定期知识库更新机制(如每周同步Notion数据库- 用`dvc`管理模型版本和训练数据 --- ### **总结** 实现个人专属的DeepSeek助手需要**分阶段实施**: 1. **基础层**:根据硬件条件选择部署方式 2. **扩展层**:通过RAG融合本地知识库 3. **定制层**:用提示词/微调适配个人需求 建议从**API+本地扩展**起步,逐步过渡到本地全量模型。关键工具链组合推荐: ``` 模型推理:vLLM/Ollama 向量数据库ChromaDB 任务编排:LangChain + Prefect 监控优化:LangSmith + Prometheus ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值