大模型RAG实战|向量数据库:Elasticsearch实现混合检索(附完整代码)

大模型RAG实战|混合检索:BM25检索+向量检索的LlamaIndex实现 目前,大模型RAG系统中普遍采用混合检索来提升检索准确性。针对要回答的问题,同时通过。 阅读详情
AI摘要

本文是大模型RAG实战系列,介绍使用LlamaIndex框架构建本地大模型知识库问答系统。涵盖知识库管理等主题,讲解向量数据库选择,如Chroma、Milvus等,重点介绍Elasticsearch用于混合检索。还给出代码实现示例,最后分享AI大模型学习资料。

大模型RAG实战系列文章,带你深入探索使用LlamaIndex框架,构建本地大模型知识库问答系统。本系列涵盖知识库管理、检索优化、模型本地部署等主题,通过代码与实例,讲解如何打造生产级系统,实现本地知识库的快速检索与智能问答。

当时,我们采用的向量数据库是Chroma,作为LlamaIndex中的向量存储(Vector Store)。Chroma是一个非常简单易用的嵌入式向量数据库,在开发和测试场景非常受欢迎。

但是,如果是生产级系统,我们必须考虑能力更强、可扩展的向量数据库,比如国内使用较多的Milvus,以及国外使用较多的Weaviate。

LlamaIndex支持超过20种向量数据库,在官网文档上给出了列表,并标注了各个向量数据库是否支持下列5个特性,包括:元数据过滤、混合检索、可删除、文档存储、支持异步。

详情请参考官方文档:

https://docs.llamaindex.ai/en/stable/module_guides/storing/vector_stores/

1、选择向量数据库

最初,QAnything使用了Milvus做向量存储和向量语义检索,后来引入了Elasticsearch做BM25关键词检索,从而实现了混合检索。

Elasticsearch作为一个分布式的搜索和数据分析引擎,在全文检索和海量非结构化数据存储等场景,已经得到了广泛应用。现在,Elasticsearch也可以用于向量存储,并支持以上包括混合检索在内的全部5个特性。

因此,在生产环境,使用Elasticsearch作为向量数据库并使用其混合检索功能,是一个合适的选择。

系统技术栈如下表所示:

数据框架LlamaIndex
前端框架Streamlit
大模型工具Ollama
大模型Gemma 2B
嵌入模型BAAI/bge-small-zh-v1.5
文本分割器SpacyTextSplitter
文档存储MongoDB
向量存储ElasticSearch

以下,我将结合代码实例,讲解如何在LlamaIndex框架中使用Elasticsearch,并给出一套完整可运行的本地知识库问答系统。

2

代码实现示例

示例1:安装和配置ES

我们使用ES做向量存储(Vector Stores)。首先,使用ES官方Docker镜像,在本机安装和运行ES。

docker run -p 9200:9200 \
  -e "discovery.type=single-node" \
  -e "xpack.security.enabled=false" \
  -e "xpack.license.self_generated.type=trial" \
  docker.elastic.co/elasticsearch/elasticsearch:8.13.2

然后,配置ES,作为向量数据库,并通过retrieval_strategy配置使用混合检索(hybrid=true)。


# 向量数据库: Elasticsearch

from llama_index.vector_stores.elasticsearch import ElasticsearchStore
from llama_index.vector_stores.elasticsearch import AsyncDenseVectorStrategy

ES_URI = "http://localhost:9200"

es_vector_store = ElasticsearchStore(
    es_url=ES_URI,
    index_name="my_index",
    retrieval_strategy=AsyncDenseVectorStrategy(hybrid=True), # 使用混合检索
)

示例2:配置MongoDB

我们选用MongoDB做文档存储(Document Stores)和索引存储(Index Stores)。你可以通过Docker安装和运行MongoDB,然后做如下代码配置。

# 文档存储: MongoDB

from llama_index.storage.docstore.mongodb import MongoDocumentStore
from llama_index.storage.index_store.mongodb import MongoIndexStore
from llama_index.core import StorageContext

MONGO_URI = "mongodb://localhost:27017"

mongo_doc_store = MongoDocumentStore.from_uri(uri=MONGO_URI)
mongo_index_store = MongoIndexStore.from_uri(uri=MONGO_URI)

storage_context = StorageContext.from_defaults(
    docstore=mongo_doc_store,
    index_store=mongo_index_store,
    vector_store=es_vector_store,
)

示例3:配置本地模型

请到ollama.com安装Ollama,并下载大模型,比如:Llama 3, Phi 3, Mistral, Gemma等。为了测试方便,我们选用速度更快、效果较好的Gemma 2B模型,共1.7GB。

# Ollama本地LLM: gemma:2b

from llama_index.llms.ollama import Ollama
llm_ollama = Ollama(model="gemma:2b", request_timeout=600.0)

嵌入模型我们继续使用智源的BAAI/bge-small-zh-v1.5。

# 本地嵌入模型: bge-small-zh-v1.5

from llama_index.embeddings.huggingface import HuggingFaceEmbedding
bge_embed_model = HuggingFaceEmbedding(model_name="BAAI/bge-small-zh-v1.5")

第一次运行时会自动从Hugging Face下载模型,请提前设置使用国内镜像站点。

export HF_ENDPOINT=https://hf-mirror.com

将配置好的大模型和嵌入模型,挂载在LlamaIndex全局设置上。

# LlamaIndex全局配置

from llama_index.core import Settings
Settings.llm = llm_ollama
Settings.embed_model = bge_embed_model

示例4:配置文本分割器

文本分割器Spacy对中文支持较好。我们可以通过Langchain引入和使用。

# 文本分割器: SpacyTextSplitter

from llama_index.core.node_parser import LangchainNodeParser
from langchain.text_splitter import SpacyTextSplitter
spacy_text_splitter = LangchainNodeParser(SpacyTextSplitter(
    pipeline="zh_core_web_sm", 
    chunk_size = 512,
    chunk_overlap = 128
))

示例5:加载网页信息

此前文章介绍过,我们可以用LlamaIndex的SimpleDirectoryReader读取本地文件夹“data”中的文件。

# 加载文件信息: SimpleDirectoryReader

from llama_index.core import SimpleDirectoryReader
documents = SimpleDirectoryReader(input_dir="./data", recursive=True).load_data() 
print(f"Loaded {len(documents)} Files")

为了测试方便,本程序中,我们用SimpleWebPageReader读取网页信息。

# 加载网页信息: SimpleWebPageReader

from llama_index.readers.web import SimpleWebPageReader

pages = ["https://mp.weixin.qq.com/s/prnDzOQ8HjUmonNp0jhRfw",]
documents = SimpleWebPageReader(html_to_text=True).load_data(pages)
print(f"Loaded {len(documents)} Web Pages")

示例6:配置数据转换管道

通过配置数据转换管道,可以实现数据转换并行处理以及知识库的去重,即默认的策略为更新插入(upserts)。

# 数据转换管道

from llama_index.core.ingestion import IngestionPipeline
pipeline = IngestionPipeline(
    transformations=[
        spacy_text_splitter,
        bge_embed_model,
    ],
    docstore=mongo_doc_store,
    vector_store=es_vector_store,
)

接下来,运行数据转换管道,将分片后的文本向量化之后,存储到Elasticsearch向量数据库中。

# 生成索引存入向量数据库

nodes = pipeline.run(documents=documents)
print(f"Ingested {len(nodes)} Nodes")
print(f"Load {len(pipeline.docstore.docs)} documents into docstore")

示例7:创建索引

然后,基于上述生成的nodes,创建向量存储索引。

# 创建向量存储索引 

from llama_index.core import VectorStoreIndex
index = VectorStoreIndex(nodes, storage_context=storage_context)

示例8:定制中文Prompt模板

为了避免大模型用英文回答中文问题,我们需要定制LlamaIndex的Prompt模板。

# 定制中文Prompt

from llama_index.core import PromptTemplate

text_qa_template_str = (
    "以下为上下文信息\n"
    "---------------------\n"
    "{context_str}\n"
    "---------------------\n"
    "请根据上下文信息回答我的问题或回复我的指令。前面的上下文信息可能有用,也可能没用,你需要从我给出的上下文信息中选出与我的问题最相关的那些,来为你的回答提供依据。回答一定要忠于原文,简洁但不丢信息,不要胡乱编造。我的问题或指令是什么语种,你就用什么语种回复。\n"
    "问题:{query_str}\n"
    "你的回复:"
)

示例9:创建查询引擎

基于索引,创建查询引擎(Query Engine)。现在,可以针对知识库中的内容进行提问了。

# 创建查询引擎并查询

query_engine = index.as_query_engine(
    text_qa_template = text_qa_template,
    top_k=1,
)

your_question = "什么是流程?"
print(f"问题:{your_question}")
response = query_engine.query(your_question)
print(f"回答:{response}")

示例10:前端UI使用Streamlit

我们使用Streamlit构建一个Web UI,用于对话。

# 使用Streamlit构建Web UI

import streamlit as st

TITLE = "本地大模型知识库问答"
st.set_page_config(page_title=TITLE, page_icon="🦙", layout="centered", initial_sidebar_state="auto", menu_items=None)
st.header(TITLE)
st.info("By 大卫", icon="📃")

if "messages" not in st.session_state.keys(): # 初始化聊天历史记录
    st.session_state.messages = [
        {"role": "assistant", "content": "关于文档里的内容,请随便问"}
    ]

# 提示用户输入问题,并将问题添加到消息历史记录
if prompt := st.chat_input("Your question"): 
    st.session_state.messages.append({"role": "user", "content": prompt})

# 显示此前的问答记录
for message in st.session_state.messages: 
    with st.chat_message(message["role"]):
        st.write(message["content"])

# 生成回答
if st.session_state.messages[-1]["role"] != "assistant": 
    with st.chat_message("assistant"):
        with st.spinner("Thinking..."):
            response = query_engine.query(prompt)
            st.write(response.response)
            message = {"role": "assistant", "content": response.response}
            st.session_state.messages.append(message)

以上全部代码,合起来形成一个文件app.py,可以通过以下命令运行。

streamlit run app.py

请注意提前通过pip命令,安装llama-index、streamlit、zh-core-web-sm、html2text等本程序运行所需的组件。

参考资料:

  • https://docs.llamaindex.ai/en/stable/examples/vector_stores/ElasticsearchIndexDemo/
  • https://docs.llamaindex.ai/en/stable/examples/docstore/MongoDocstoreDemo/

​

如何学习AI大模型?

作为一名热心肠的互联网老兵,我决定把宝贵的AI知识分享给大家。 至于能学习到多少就看你的学习毅力和能力了 。我已将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。

这份完整版的大模型 AI 学习资料已经上传优快云,朋友们如果需要可以微信扫描下方优快云官方认证二维码免费领取【保证100%免费】

一、全套AGI大模型学习路线

AI大模型时代的学习之旅:从基础到前沿,掌握人工智能的核心技能!

img

二、640套AI大模型报告合集

这套包含640份报告的合集,涵盖了AI大模型的理论研究、技术实现、行业应用等多个方面。无论您是科研人员、工程师,还是对AI大模型感兴趣的爱好者,这套报告合集都将为您提供宝贵的信息和启示。

img

三、AI大模型经典PDF籍

随着人工智能技术的飞速发展,AI大模型已经成为了当今科技领域的一大热点。这些大型预训练模型,如GPT-3、BERT、XLNet等,以其强大的语言理解和生成能力,正在改变我们对人工智能的认识。 那以下这些PDF籍就是非常不错的学习资源。

img

四、AI大模型商业化落地方案

img

作为普通人,入局大模型时代需要持续学习和实践,不断提高自己的技能和认知水平,同时也需要有责任感和伦理意识,为人工智能的健康发展贡献力量。

详细教程:如何使用elasticsearch 8.x进行向量搜索 大模型的热度使得向量数据库和embedding也成了ai领域的热门话题,有别于从头开始训练一个大模型或基于基础模型进行微调的方式,embedding检索相关上下文是对大模型进行定制的各种方法中成本最低、技术实现最便捷的方式。从技术实现的角度, 阅读详情

相关推荐

ES混合检索

2024年06月上线 ES 8.13.3版本,该版本在向量检索、NLP能力等方面表现更优。为AI革命提供高级搜索能力!腾讯云大数据ES国内首发上线8.8.1版本利用Elasticsearch作为向量数据库,有效地创建、存储和搜索密集向量。提供图索引,通过HNSW以实现高效的最近邻搜索;支持端到端的向量生成、向量索引、向量相似性比较,无需额外的平台进行向量推理;一体化的搜索体验:多路召回混合打分、Faceting聚合分析能力、基于角色的访问控制;

技术引领业务创新 1581

再仔细品品Elasticsearch的向量检索

我在es一开始有向量检索,就开始关注这方面内容了。特别是在8.X之后的版本,更是如此。我也已经把它应用在亿级的生产环境中,用于多模态检索和语义检索,以及RAG相关。这篇文章再带大家品一品es的向量检索。

Angus 4499

LlamaIndex实现RAG增强:融合检索(Fusion Retrieval)与混合检索(Hybrid Search)

本代码实现了一个混合检索系统,将基于向量的相似性搜索与基于关键词的BM25检索相结合。该方法旨在综合两种技术的优势,提升文档检索的整体质量和相关性。

AI人工智能的学习之路 2685

Elasticsearch 向量检索详解

Elasticsearch 的向量检索是一种强大的技术,适用于处理高维向量数据的相似性搜索。通过将文本、图像等数据转换为向量,并结合高效的相似度计算,可以实现语义搜索、图像搜索、推荐系统等复杂场景。掌握向量检索的原理和使用方法,可以帮助开发者构建更智能的搜索应用。

Elastic开源社区 2319

【RAG】混合检索(Hybrid Search) 提高检索精度

RAG基于 RRF 的融合排序,融合向量检索、关键词检索 等检索算法,提高检索精度

weixin_42430947的博客 1869

02-Elasticsearch AI 大模型搜索引擎介绍与演示 meetup 成都 8.19 2023

02-Elasticsearch AI 大模型搜索引擎介绍与演示 meetup 成都 8.19 2023

大模型之RAG-关键字检索的认识与实战(混合检索进阶储备)

首先,RAG不是一个单项技术,它是一个流水线,行话叫pipeline。只有对流水线上的每一步骤都进行精细打磨,最后才能出来效果,我们的目标就是努力使每个环节都达到尽可能准确本文我们对关键字检索做了讲解以及从实战的角度做了讲解。首先我们应该认识到RAG的核心在于外部知识库,这个外部知识库甚至可以是基于关系型数据库的sql查询。而本文基于ES的关键字检索也是一个比较传统和基础的检索方式,他比较简单,也有它适用的场景。

2401_85325726的博客 2272

稳压电源的隐形战场:动态特性如何影响你的嵌入式系统稳定性

本文深入探讨了稳压电源动态特性对嵌入式系统稳定性的关键影响,分析了HT7533和AMS1117等稳压芯片在输入阶跃响应和负载瞬态响应方面的性能差异。通过实测案例展示了不同场景下的动态特性表现,并提供了针对工业控制、IoT设备和射频系统的选型指南与优化策略,帮助工程师解决电源相关的隐蔽故障。

weixin_29204205的博客 609

手把手实现RAG混合检索:Elasticsearch向量数据库实战教程(附代码)

本文介绍如何基于LlamaIndex框架构建生产级本地知识库问答系统,重点讲解使用Elasticsearch作为向量数据库的实践方法。系统采用混合检索技术(Elasticsearch+BGE嵌入模型),搭配MongoDB文档存储、Ollama本地大模型(Gemma 2B)和Streamlit前端界面。文章详细展示了从环境配置(ES/MongoDB容器部署)、模型加载(嵌入模型与提示模板定制)、数据处理(网页信息加载与文本分割)到查询引擎构建的全流程代码实现,最终形成一个支持中文问答的完整解决方案。通过该方案

2401_85154887的博客 1218

用WorkBuddy和ima搭建本地知识库:从概念到实操

在AI应用普及的今天,私有知识的高效管理与调用成为痛点。RAG(检索增强生成)技术通过将外部知识库与语言模型耦合,为精准问答提供了技术底座。然而,传统RAG方案往往涉及向量数据库、文本切分等复杂环节。一种更轻量的路径应运而生:借助WorkBuddy与ima的组合,将知识收集、语义检索与智能体工作流整合,让本地知识库真正服务于日常办公和研发场景。从概念到实操,系统解析这套轻量级方案的核心逻辑与配置方法,并对比重方案适用边界,帮助读者快速搭建属于自己的AI知识助手。

weixin_32830601的博客 420

12V INPUT电源电路设计中的关键保护机制解析【精简】

本文深入解析了12V INPUT电源电路设计中不可或缺的关键保护机制。针对常见的电源反接、过压及浪涌等风险,文章详细拆解了PMOS防反接、TVS过压钳位、OVP芯片关断以及快速断电电路等核心防护方案的设计原理、选型要点与实战优化技巧,旨在帮助工程师构建可靠、经济的电源前端防御体系。

weixin_29158047的博客 228

【原创】使用ElasticSearch存储向量实现大模型RAG

检索增强生成(Retrieval-Augmented Generation,RAG)已成为大型语言模型(LLM)应用的重要架构,通过结合外部知识库来增强模型的回答能力,特别是在处理专业领域知识、最新信息或企业私有数据时。本报告将系统梳理使用 Elasticsearch(ES)作为向量数据库实现 RAG 系统的优缺点,与传统向量数据库及其他存储解决方案的对比,以及基于 Deepseek V3 和 Qwen2.5 大模型的实现方案。多层图结构:HNSW 构建一个多层的图结构,顶层包含少量节点,底层包含所有节点。

heiyeluren的blog(黑夜路人的开源世界) 4588

Winform零基础从入门到精通(3)——WinForm基础语法与事件机制详解

通过系统学习基础语法与事件机制,结合实际问题调试,可以快速掌握WinForm开发的核心技能。遇到问题时,优先检查事件绑定和异常处理,逐步培养代码规范意识。​安全转换字符串为数值,避免输入错误导致的崩溃。验证输入(如仅允许数字)​)传递事件相关数据。◦ 事件参数类型:​。

WangMing_X的博客 1492

RAG大模型实战:关键字检索的深度解析与混合检索技巧

首先,RAG不是一个单项技术,它是一个流水线,行话叫pipeline。只有对流水线上的每一步骤都进行精细打磨,最后才能出来效果,我们的目标就是努力使每个环节都达到尽可能准确本文我们对关键字检索做了讲解以及从实战的角度做了讲解。首先我们应该认识到RAG的核心在于外部知识库,这个外部知识库甚至可以是基于关系型数据库的sql查询。而本文基于ES的关键字检索也是一个比较传统和基础的检索方式,他比较简单,也有它适用的场景。

2401_84204413的博客 1623

使用OpenTK展示3D点云图像(C#)

图中存在一个空的点,可通过阈值分割过滤掉,然后如何保证某个点必然存在后面两个和它构成三角形的点,用一个2x2的结构元腐蚀阈值分割出的区域,得到剩下所有的点必然每个点可以构成三角形,这种得到三角形的算法效率会非常高。然后还有光照,无光照和有光照效果差异很大,处理光照核心在于得到每个点的法向量,用上面的三角形的两条边构成的向量叉乘,及得到这个点的法向量,输入给着色器处理得到光照的渲染效果,如下面两张图对比。我们需要把点连成面,有很多算法可以实现,但我拿到的图为一张tif格式16位的深度图,如下图。

海盗Isaac 2283

ai获客系统功能代码

AI 获客系统是一个复杂的体系,以下为你提供一个简化的 Python 示例,聚焦于客户行为分析与销售线索筛选功能,模拟实现从多渠道收集数据后的初步处理流程。假设已有从官网、线上商城等渠道收集到的客户数据,以字典列表形式存储,每个字典包含客户基本信息及购买行为数据。通过分析客户购买频率与金额,筛选出高价值销售线索。python上述代码仅为基础示例,实际 AI 获客系统还涉及更复杂的数据采集、清洗、存储,以及运用机器学习算法进行深度客户洞察等功能。

weixin_ggwwsscc的博客 892

RAG大模型关键字检索技巧,进阶混合检索技能储备指南

按照我们之前的分享([大模型应用RAG系列3-1从0搭建一个RAG:做好文档切分]):RAG系统搭建的基本流程今天我们分享一个实现的场景:看到本文,可能有的jy会问,现在不都是在讲基于向量数据库的向量检索么,还需要专门再学习关键字检索么。随着RAG的发展,单纯的关键字检索或者向量检索都很难满足我们面临的复杂场景,了解关键字检索是为了后面更好的去了解,以及为什么会出现混合检索。关键字检索是通过匹配查询中的关键字与文档中的关键字来进行检索的。当用户输入一个查询时,系统会在文档集合中查找包含这些关键字的文档,并将

2401_85375186的博客 1007

【应用】打造你的安全本地AI购物助手:OpenClaw + 淘宝MCP部署全攻略

本文介绍了在Ubuntu虚拟机中配置OpenClaw连接Windows宿主机的淘宝MCP服务的两种方案。核心原理是通过修改MCP服务监听地址或SSH隧道转发,实现跨网络访问。方案1推荐修改MCP服务绑定0.0.0.0并配置防火墙放行端口,适合长期使用;方案2通过SSH隧道转发,适合临时测试。文章详细说明了环境准备、配置文件修改及两种互通方案的具体实施步骤,重点解决了虚拟机与宿主机网络互通的关键问题。

海兰 1323

RAG 、Embedding与向量数据库

向量是一种有大小和方向的数学对象。它可以表示为从一个点到另一个点的有向线段。例如,二维空间中的向量可以表示为 (x,y),表示从原点 (0,0) 到点 (x,y) 的有向线段。以此类推,我可以用一组坐标 (x0,x1,…,xN−1) 表示一个 N 维空间中的向量,N 叫向量的维度。文本向量是N维表示,一般的嵌入式模型,维度一般是1000+,对于openai来说:维度为 1536,是 OpenAI 较为常用的文本嵌入模型,能在多种自然语言处理任务中表现出色,可捕捉文本中较为细致的语义信息。

weixin_36998410的博客 2361

Bean named‘ddlApplicationRunner‘is expected to be of type ‘org.springframework.boot.Runner‘

springboot3.1.7整合mybatisplus3.5.3.2版本报错,sringboot3.x整合myabtis报错

雾林小妖的博客 1万+

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

检索引擎深度对比:Elasticsearch vs Milvus vs Redis 在 RAG 中的定位

你的数据特征:有没有大量精确词?向量规模多大?增长率如何?你的延迟预算:全链路 1 秒还是 3 秒?检索环节的延迟占比多少?你的运维能力:团队有没有精力再维护一个专用数据库?ES 适合关键词密集、需要复杂过滤的场景。Milvus 适合大规模纯向量搜索。Redis 适合中小规模、延迟敏感、团队运维能力有限的场景。我的建议:先用 Redis 做 PoC(部署快、延迟低、和缓存一体化),当向量规模到百万级时评估是否需要迁移 Milvus。ES 只在"非用不可"的场景上——它的运维成本比另外两个都高。

2401_87746054的博客 9913

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

上一篇: 大模型好书分享:《精通Transformer,从零开始构建最先进的NLP模型》(附PDF)
下一篇: 斯坦福大学人工智能图书馆收藏的这本大模型黑书到底有何魔力?
AI程序猿人
博客等级 码龄3年 6517粉丝 561原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值