用免费 Embedding API 构建 RAG 知识库
Retrieval-Augmented Generation(RAG)是当下最实用的 AI 应用模式——让 LLM 在回答时"参考"你的私有知识库,而不是凭空编造。本文手把手教你用免费 API 从零搭建一个完整 RAG 系统。
RAG 架构速览
用户提问 → 向量化查询 → 向量数据库检索 → 召回相关文档片段 → 拼接 Prompt → LLM 生成回答
核心组件:
| 组件 |
用途 |
免费选择 |
| Embedding 模型 |
向量化文档和查询 |
OpenAI text-embedding-3-small / BGE-m3 |
| 向量数据库 |
存储和检索向量 |
Chroma(开源)/ LanceDB |
| LLM |
生成最终回答 |
Gemini 1.5 Flash / DeepSeek / Groq |
| 文档加载器 |
解析 PDF/网页/Markdown |
LangChain / LlamaIndex |
第一步:环境准备
pip install chromadb openai langchain langchain-community
通过 APIShare 统一接入,只需一个 token 就能调用多种 Embedding 和 LLM:
import os
os.environ["OPENAI_API_KEY"] = "your-apishare-token"
os.environ["OPENAI_BASE_URL"] = "https://apishare.cc/v1"
第二步:加载并切分文档
from langchain_community.document_loaders import TextLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
# 加载你的知识库文档
loader = TextLoader("./knowledge_base.txt")
documents = loader.load()
# 切分为 500 字符的块,重叠 50 字符
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=500,
chunk_overlap=50,
separators=["\n\n", "\n", "。", "!", "?", " ", ""]
)
chunks = text_splitter.split_documents(documents)
print(f"共切分 {len(chunks)} 个文档块")
第三步:向量化并存入 Chroma
用免费 Embedding API 将文档块转为向量:
from langchain_openai import OpenAIEmbeddings
from langchain_community.vectorstores import Chroma
# 使用 OpenAI 兼容的 Embedding API
embedding = OpenAIEmbeddings(
model="text-embedding-3-small",
dimensions=512 # 降维节省存储
)
# 向量化并存入 Chroma
vectorstore = Chroma.from_documents(
documents=chunks,
embedding=embedding,
persist_directory="./chroma_db"
)
print(f"向量数据库已创建,共 {len(chunks)} 条记录")
如果追求更好的中文效果,可以切换为 BGE-m3:
# 使用 Hugging Face 的 BGE-m3(通过 APIShare 统一路由)
embedding = OpenAIEmbeddings(
model="BAAI/bge-m3",
openai_api_base="https://apishare.cc/v1",
dimensions=1024
)
第四步:构建检索器
retriever = vectorstore.as_retriever(
search_type="mmr", # 最大边际相关性,兼顾相关性和多样性
search_kwargs={"k": 5} # 返回 Top 5 最相关文档块
)
# 测试检索
query = "APIShare 支持哪些 Embedding 模型?"
results = retriever.invoke(query)
for i, doc in enumerate(results):
print(f"--- 结果 {i+1} ---")
print(doc.page_content[:200])
第五步:拼接 Prompt 并调用 LLM
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough
from langchain_core.output_parsers import StrOutputParser
# 使用免费 LLM
llm = ChatOpenAI(
model="gemini-2.0-flash", # 或 deepseek-chat、groq/llama-3.1-8b
temperature=0.3
)
# 构建 RAG Prompt 模板
template = """你是一个知识助手。请根据以下参考资料回答用户问题。
如果无法从参考资料中找到答案,请如实说明。
参考资料:
{context}
用户问题:{question}
回答:"""
prompt = ChatPromptTemplate.from_template(template)
# 组装 RAG Chain
def format_docs(docs):
return "\n\n".join(doc.page_content for doc in docs)
rag_chain = (
{"context": retriever | format_docs, "question": RunnablePassthrough()}
| prompt
| llm
| StrOutputParser()
)
# 提问!
answer = rag_chain.invoke("APIShare 支持哪些 Embedding 模型?")
print(answer)
第六步:进阶优化
6.1 混合检索(Hybrid Search)
结合关键词检索(BM25)和向量检索,兼顾精确匹配和语义召回:
from langchain.retrievers import BM25Retriever, EnsembleRetriever
# 关键词检索器
bm25_retriever = BM25Retriever.from_documents(chunks, k=3)
# 向量检索器
vector_retriever = vectorstore.as_retriever(search_kwargs={"k": 3})
# 混合检索,权重 50/50
ensemble_retriever = EnsembleRetriever(
retrievers=[bm25_retriever, vector_retriever],
weights=[0.5, 0.5]
)
6.2 重排序(Re-ranking)
对召回的文档用更强的模型重新排序,提升 Top 3 精度:
# 使用 BGE-reranker 或 Cohere Rerank 免费层
from langchain.retrievers import ContextualCompressionRetriever
from langchain_cohere import CohereRerank
compressor = CohereRerank(model="rerank-english-v3.0", top_n=3)
compression_retriever = ContextualCompressionRetriever(
base_compressor=compressor,
base_retriever=retriever
)
6.3 多轮对话支持
加入历史消息上下文,让 RAG 支持追问:
from langchain_core.messages import HumanMessage, AIMessage
chat_history = []
def rag_with_history(query):
# 检索历史感知的上下文
context_docs = retriever.invoke(query)
context = format_docs(context_docs)
messages = [
{"role": "system", "content": f"参考资料:{context}"},
*chat_history[-6:],
{"role": "user", "content": query}
]
response = llm.invoke(messages)
chat_history.append({"role": "user", "content": query})
chat_history.append({"role": "assistant", "content": response.content})
return response.content
# 第一轮
print(rag_with_history("APIShare 的免费额度是多少?"))
# 第二轮(依赖上文)
print(rag_with_history("那它支持哪些模型?"))
完整项目结构
my-rag/
├── knowledge_base.txt # 你的知识库文档
├── chroma_db/ # 向量数据库持久化目录
├── rag_engine.py # RAG 核心逻辑
├── ingest.py # 文档加载与向量化
└── query.py # 交互式查询
成本分析
| 组件 |
免费额度 |
适用场景 |
| OpenAI Embedding |
APIShare 共享池 |
开发测试,小规模知识库 |
| BGE-m3 |
1000次/天 |
中文场景,中等规模 |
| Chroma |
完全免费开源 |
任意规模 |
| Gemini 1.5 Flash |
1500次/天 |
日常 RAG 问答 |
| DeepSeek |
500次/天 |
复杂推理问答 |
零成本运行一个日均 100 次查询的 RAG 系统完全可行。
总结
本文完整演示了用免费 API 搭建 RAG 系统的全流程:文档加载 → 切分 → Embedding 向量化 → Chroma 存储 → 检索 → LLM 生成。通过 APIShare 统一入口,你可以在一个 SDK 内自由切换 Embedding 模型和 LLM,零成本构建生产级 RAG 应用。
下一步建议:
- 尝试多模态 RAG(图片 + 文字)
- 接入更多数据源(PDF、网页、数据库)
- 使用 Agent 框架实现自主决策检索
Building a RAG Knowledge Base with Free Embedding APIs
Retrieval-Augmented Generation (RAG) is the most practical AI application pattern today — letting LLMs "reference" your private knowledge base rather than hallucinating answers. This tutorial walks you through building a complete RAG system from scratch using free APIs.
RAG Architecture Overview
User Query → Embed Query → Vector DB Search → Retrieve Relevant Chunks → Assemble Prompt → LLM Generates Answer
Core components:
| Component |
Purpose |
Free Option |
| Embedding Model |
Vectorize documents and queries |
OpenAI text-embedding-3-small / BGE-m3 |
| Vector Database |
Store and search vectors |
Chroma (OSS) / LanceDB |
| LLM |
Generate final answer |
Gemini 1.5 Flash / DeepSeek / Groq |
| Document Loader |
Parse PDF/Web/Markdown |
LangChain / LlamaIndex |
Step 1: Environment Setup
pip install chromadb openai langchain langchain-community
Access multiple embedding and LLM models through APIShare with a single token:
import os
os.environ["OPENAI_API_KEY"] = "your-apishare-token"
os.environ["OPENAI_BASE_URL"] = "https://apishare.cc/v1"
Step 2: Load and Split Documents
from langchain_community.document_loaders import TextLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
loader = TextLoader("./knowledge_base.txt")
documents = loader.load()
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=500,
chunk_overlap=50,
separators=["\n\n", "\n", ".", "?", "!", " ", ""]
)
chunks = text_splitter.split_documents(documents)
print(f"Split into {len(chunks)} chunks")
Step 3: Embed and Store in Chroma
from langchain_openai import OpenAIEmbeddings
from langchain_community.vectorstores import Chroma
embedding = OpenAIEmbeddings(
model="text-embedding-3-small",
dimensions=512
)
vectorstore = Chroma.from_documents(
documents=chunks,
embedding=embedding,
persist_directory="./chroma_db"
)
print(f"Vector DB created with {len(chunks)} records")
For better Chinese performance, switch to BGE-m3:
embedding = OpenAIEmbeddings(
model="BAAI/bge-m3",
openai_api_base="https://apishare.cc/v1",
dimensions=1024
)
Step 4: Build the Retriever
retriever = vectorstore.as_retriever(
search_type="mmr",
search_kwargs={"k": 5}
)
query = "What embedding models does APIShare support?"
results = retriever.invoke(query)
for i, doc in enumerate(results):
print(f"--- Result {i+1} ---")
print(doc.page_content[:200])
Step 5: Assemble Prompt and Call LLM
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough
from langchain_core.output_parsers import StrOutputParser
llm = ChatOpenAI(
model="gemini-2.0-flash",
temperature=0.3
)
template = """You are a knowledgeable assistant. Answer based on the reference materials below.
If you cannot find the answer in the references, say so honestly.
Reference Materials:
{context}
User Question: {question}
Answer:"""
prompt = ChatPromptTemplate.from_template(template)
def format_docs(docs):
return "\n\n".join(doc.page_content for doc in docs)
rag_chain = (
{"context": retriever | format_docs, "question": RunnablePassthrough()}
| prompt
| llm
| StrOutputParser()
)
answer = rag_chain.invoke("What embedding models does APIShare support?")
print(answer)
Step 6: Advanced Optimization
6.1 Hybrid Search
Combine keyword (BM25) and vector retrieval for precision + semantics:
from langchain.retrievers import BM25Retriever, EnsembleRetriever
bm25_retriever = BM25Retriever.from_documents(chunks, k=3)
vector_retriever = vectorstore.as_retriever(search_kwargs={"k": 3})
ensemble_retriever = EnsembleRetriever(
retrievers=[bm25_retriever, vector_retriever],
weights=[0.5, 0.5]
)
6.2 Re-ranking
Re-rank retrieved documents with a stronger model for better Top-3 precision:
from langchain.retrievers import ContextualCompressionRetriever
from langchain_cohere import CohereRerank
compressor = CohereRerank(model="rerank-english-v3.0", top_n=3)
compression_retriever = ContextualCompressionRetriever(
base_compressor=compressor,
base_retriever=retriever
)
6.3 Multi-turn Conversation
Add chat history for follow-up question support:
chat_history = []
def rag_with_history(query):
context_docs = retriever.invoke(query)
context = format_docs(context_docs)
messages = [
{"role": "system", "content": f"Reference: {context}"},
*chat_history[-6:],
{"role": "user", "content": query}
]
response = llm.invoke(messages)
chat_history.append({"role": "user", "content": query})
chat_history.append({"role": "assistant", "content": response.content})
return response.content
Project Structure
my-rag/
├── knowledge_base.txt # Your knowledge base
├── chroma_db/ # Persisted vector DB
├── rag_engine.py # Core RAG logic
├── ingest.py # Document loading & embedding
└── query.py # Interactive query
Cost Analysis
| Component |
Free Tier |
Best For |
| OpenAI Embedding |
APIShare shared pool |
Dev/test, small KB |
| BGE-m3 |
1,000 calls/day |
Chinese scenarios, medium scale |
| Chroma |
Fully free & open-source |
Any scale |
| Gemini 1.5 Flash |
1,500 calls/day |
Daily RAG Q&A |
| DeepSeek |
500 calls/day |
Complex reasoning |
Running a RAG system with 100 queries/day at zero cost is entirely feasible.
Conclusion
This tutorial demonstrated the complete RAG pipeline: document loading, splitting, embedding, Chroma storage, retrieval, and LLM generation. Through APIShare's unified endpoint, you can freely switch between embedding models and LLMs within a single SDK, building production-grade RAG applications at zero cost.
Next steps:
- Try multimodal RAG (images + text)
- Integrate more data sources (PDF, web, databases)
- Use Agent frameworks for autonomous retrieval decisions