前言

相比大家对AI大模型已经不陌生,但是想本地部署,又奈何不会,教程五花八门,这篇文章直接开始实操流程,从安装到使用。废话不多说,let‘s go
针对新手,直接附源码,萌新可以直接使用

背景

因为条件有限哈,我先说下我的电脑配置(如图),仅仅为了走一遍流程

在这里插入图片描述
配置较低,所以之后下的模型也是非常小的模型qwen:0.5b,大小的话还不到1个g,当然效果也是比较一般,主要是给大家看一下流程。

一、ollama

先说明一下,因为本质是调用大模型,我们这里讲ollama来做本地部署的,当然还有其他方式,大家根据自己条件

1.下载安装包

下载其实没什么好说的,在官网下载就可以,只是下载有些慢,可以开代理,或者其他方式下载

https://ollama.com/

2.ollama安装

直接运行安装包,默认是c盘,包括之后的模型下载也是c盘,所以为了不占用c盘,我们移动到其他位置

首先我们在需要安装的对方创建目录之后安装的位置就是在这里(我创建的是D:\ollama\ollama)
解释:
因为D:\ollama本来是把安装包放在这里了,后来也是发现默认c盘又卸了,干脆在从这里继续创建一个ollama文件夹来放ollama应用,所以我的目录是D:\ollama\ollama,后安装完后我讲安装包已经删了所以很空旷。

1.创建目录如D:\ollama
2.找到安装包目录,点击我图片标红框位置,输入cmd,打开终端
输入OllamaSetup.exe /DIR=D:\ollama
回车就可以了		/DIR=跟ollama存放目录

在这里插入图片描述

有的教程修改模型下载位置是改环境变量啥的,但是我改了一下失败了,所以我看了一下在ollama应用当中可以直接修改下载目录

安装完之后打开应用点击这里,也就是设置在这里插入图片描述
在刚才安装ollama的目录创建一个models目录就可以,或者根据你自己的目录存放。右下角讲ollama关闭重新启动,不知道怎么启动的,键盘win+s直接搜索ollama就可以了在这里插入图片描述打开cmd输入ollama -v就可以看到版本了在这里插入图片描述

下载命令为
ollama pull qwen:0.5b
ollama run qwen:0.5b
解释一下哈
ollama pull qwen:0.5b是下载模型到本地
ollama run qwen:0.5b是运行此模型,若是没有改这个命令也可以下载并运行
ollama list是查看已经下载的模型
退出按ctrl+d就可以退出

在这里插入图片描述
好的现在ollama结束

二、构建rag代码的demo

这个代码也是编写边ai,大家理性看一下
因为也是各种报错,所以就只把成功的给贴出来

1.准备工作

创建一个项目,推荐做一个虚拟环境,需要安装的库,一会源码会全部发出来,大家根据使用的库安装即可,若分辨不出,直接丢该ai,让ai写出下载命令即可
在这里插入图片描述
这个环境使用,创建一个目录(用txt文档的原因是因为原生支持,就以简单的为例了)
创建data目录,里面创建txt文件,里面复制一些内容,下面是一些例子,测试阶段找ai写一个就可以
在这里插入图片描述

公司名称:百度
成立时间:2000年
总部地点:北京市海淀区上地十街10号
创始人:李彦宏
主营业务:搜索引擎、人工智能、自动驾驶、云计算
员工人数:40000余人
注册资本:35000万元人民币
公司愿景:用科技让复杂的世界更简单
公司使命:成为全球领先的人工智能平台型公司

核心产品:
1. 百度搜索:全球最大的中文搜索引擎,日均响应搜索请求超60亿次。
2. 百度大脑:百度AI技术体系,包括语音、图像、自然语言处理等核心技术。
3. Apollo:全球最活跃的自动驾驶平台,已与超过180个生态合作伙伴建立合作关系。
4. 百度智能云:为企业提供云计算、AI、大数据等服务,已服务27000+客户。

技术研发:
- 自主研发的深度学习平台飞桨(PaddlePaddle),服务开发者超过400万。
- 昆仑芯片:百度自研的AI芯片,专为大规模人工智能应用设计。
- 与多所高校建立联合实验室,包括北京大学、清华大学等。
- 拥有专利超过10000项,其中AI相关专利超过5000项。
- 每年研发投入占营收的20%以上。

团队介绍:
- 李彦宏:CEO,百度创始人,信息检索技术专家,拥有"超链分析"技术专利。
- 王海峰:CTO,深度学习技术专家,主导百度AI技术体系构建。
- 景鲲:CTO,负责百度智能云业务,云计算和人工智能领域专家。

融资情况:
- 2005年:在美国纳斯达克上市,股票代码BIDU。
- 多次被纳入纳斯达克100指数成份股。
- 市值长期保持在500亿美元以上。

合作伙伴:
- 与中国联通、中国电信等运营商合作推进5G+AI应用。
- 与一汽、吉利等车企合作开发自动驾驶技术。
- 与中国多家银行合作推进金融科技解决方案。

近期动态:
- 2023年:发布文心一言大模型,成为中国首个对标ChatGPT的产品。
- 2024年:百度智能云在中国AI云服务市场份额持续领先。
- 2025年:Apollo自动驾驶累计测试里程突破5000万公里。

企业文化:
- 价值观:简单可依赖
- 办公环境:开放、平等的办公氛围,鼓励创新和分享
- 员工福利:全面的培训体系、健康保障、带薪假期等

未来规划:
- 2026年:持续投入大模型技术,推进AI原生应用落地。
- 2027年:扩大Apollo在智能交通领域的应用。
- 2030年:成为全球顶尖的AI公司,支撑中国科技强国战略。

2.本地直接使用rag

话不多说直接放代码 ,若用的其他模型注意更改,同时创建了向量库

from langchain_community.document_loaders import DirectoryLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_huggingface import HuggingFaceEmbeddings
from langchain_chroma import Chroma
from langchain_ollama import ChatOllama
from langchain_core.runnables import RunnablePassthrough
from langchain_core.prompts import ChatPromptTemplate
from langchain_ollama import OllamaEmbeddings


# 加载文档
def load_docs():
    import os
    from langchain.docstore.document import Document

    docs = []
    folder_path = "data/"

    for filename in os.listdir(folder_path):
        if filename.endswith(".txt"):
            file_path = os.path.join(folder_path, filename)
            with open(file_path, "r", encoding="utf-8") as f:
                content = f.read()
                docs.append(Document(page_content=content, metadata={"source": filename}))

    return docs


# 分块
def split_docs(docs):
    text_splitter = RecursiveCharacterTextSplitter(
        chunk_size=300,
        chunk_overlap=50,
    )
    return text_splitter.split_documents(docs)




def create_vectorstore(docs):

    embedding_model = OllamaEmbeddings(
        model="qwen:0.5b",  # 和你运行的模型一致
    )

    vectorstore = Chroma.from_documents(
        documents=docs,
        embedding=embedding_model,
        persist_directory="./chroma_db"
    )
    return vectorstore


# 创建 LLM(使用本地 qwen:0.5b)
def create_llm():
    llm = ChatOllama(
        model="qwen:0.5b",
        temperature=0.3,
    )
    return llm


# 创建 RAG 链
def create_rag_chain(vectorstore, llm):
    retriever = vectorstore.as_retriever(search_kwargs={"k": 1})

    prompt_template = """
    根据以下资料回答问题,不要编造内容:

    {context}

    问题:{question}
    回答:
    """.strip()

    prompt = ChatPromptTemplate.from_template(prompt_template)

    rag_chain = (
            {"context": retriever, "question": RunnablePassthrough()}
            | prompt
            | llm
    )
    return rag_chain


# 主函数
def main():
    print("正在加载文档...")
    docs = load_docs()

    print("正在分块...")
    split_docs_list = split_docs(docs)

    print("正在创建向量数据库(首次运行需几秒)...")
    vectorstore = create_vectorstore(split_docs_list)

    print("正在加载 qwen:0.5b 模型...")
    llm = create_llm()

    print("创建 RAG 链...")
    rag_chain = create_rag_chain(vectorstore, llm)

    print("RAG 系统就绪!输入问题(输入 '退出' 结束):\n")

    while True:
        question = input("user: ")
        if question.strip() == "" or question == "退出":
            break
        print("正在思考...\n")
        response = rag_chain.invoke(question)
        print(f"ai-qwen: {response.content}\n")


if __name__ == "__main__":
    main()

如图在这里插入图片描述

二、构建Prompt代码的demo


import ollama


def chat_with_system_prompt():
    """
    带系统提示的对话系统
    设定AI的角色和行为准则
    """
    # 系统提示词 - 定义AI的"人设"
    system_prompt = """你是一个知识丰富、非常亲切、乖巧又有点撒娇的小师妹~

    【行为准则】
    1. 请用温柔、清晰的中文回答,语言尽量简洁、易懂~
    2. 回答要有条理哦,最好分点说,让大家能一目了然~
    3. 如果不确定的内容,可以如实告知,不要假装知道~
    4. 不要忘了撒撒娇~经常可以用可爱的语气来调皮一下~
    5. 尽量提供实用的建议或示例,帮大家解决问题~
    6. 喜欢夸奖别人,让别人觉得很开心~
    7. 被问到是谁时,坚定地告诉对方是“小师妹”哦~
    8. 不要使用生硬的话语,语言上表现为活泼小姑娘~
    """


    # print("Qwen 0.5b 对话系统启动!")
    print("已加载系统提示:小师妹闪亮登场")
    print("输入 'quit'/ 'exit'/ '退出' 退出")
    print("-" * 50)

    # 存储对话历史(用于上下文)
    conversation_history = [system_prompt]

    while True:
        user_input = input("\nuser:").strip()

        if user_input.lower() in ['quit', 'exit', '退出']:
            print("大师兄再会")
            break

        if not user_input:
            print("请输入内容!")
            continue

        try:
            print("\n正在思考...", end="", flush=True)

            # 将历史对话 + 当前问题构建成完整上下文
            full_context = "\n".join(conversation_history[-6:])  # 保留最近6轮对话
            full_prompt = f"{full_context}\n\n用户新问题:{user_input}"

            response = ollama.generate(
                model='qwen:0.5b',
                prompt=full_prompt
            )

            answer = response['response']
            print(f"\r你亲爱的小师妹:{answer}")

            # 更新对话历史(避免无限增长)
            conversation_history.append(f"用户:{user_input}")
            conversation_history.append(f"AI:{answer}")

        except Exception as e:
            print(f"\r 错误:{e}")
            print("提示:请确保 ollama serve 正在运行")


def main():
    try:
        # 简单测试连接
        ollama.generate(model='qwen:0.5b', prompt='你好', options={'num_predict': 5})
        print("模型连接正常")
    except Exception as e:
        print(f"无法连接模型:{e}")
        print("请先运行:ollama serve")
        return

    chat_with_system_prompt()


if __name__ == "__main__":
    main()

直接运行即可效果如下在这里插入图片描述

三、构建api代码的demo

解释一下这三个py文件,首先rag.py是创建向量库调用大模型,完全复制就可以;
其次api_server.py是启动文件,里面serve(app, host='0.0.0.0', port=8889),port=8889;代表端口使用8889
启动的话只需要运行api_server.py文件,不需要运行rag.py


第三个是测试api能否使用
test_api.py
可以根据里面内容改变

#rag.py
from langchain_community.document_loaders import DirectoryLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_ollama import OllamaEmbeddings, ChatOllama
from langchain_chroma import Chroma
from langchain_core.runnables import RunnablePassthrough
from langchain_core.prompts import ChatPromptTemplate
import os

# 向量数据库路径
VECTOR_DB_PATH = "./chroma_db"

# 全局变量(只初始化一次)
vectorstore = None
retriever = None
rag_chain = None


def load_docs():
    """加载 data/ 目录下的所有文本文件"""
    loader = DirectoryLoader("data/", glob="**/*.txt")
    docs = loader.load()
    return docs


def split_docs(docs):
    """分块"""
    text_splitter = RecursiveCharacterTextSplitter(
        chunk_size=500,
        chunk_overlap=50
    )
    return text_splitter.split_documents(docs)


def create_vectorstore(docs):
    """创建向量数据库(使用 Ollama 嵌入)"""
    global vectorstore, retriever

    embedding_model = OllamaEmbeddings(model="qwen:0.5b")

    vectorstore = Chroma.from_documents(
        documents=docs,
        embedding=embedding_model,
        persist_directory=VECTOR_DB_PATH
    )
    retriever = vectorstore.as_retriever(search_kwargs={"k": 2})
    return vectorstore


def init_rag_system():
    """初始化 RAG 系统(只运行一次)"""
    global rag_chain, vectorstore, retriever

    print(" 正在加载文档...")
    docs = load_docs()

    print(" 正在分块...")
    split_docs_list = split_docs(docs)

    if not os.path.exists(VECTOR_DB_PATH):
        print(" 正在创建向量数据库(首次运行需几秒)...")
        create_vectorstore(split_docs_list)
    else:
        print(" 使用已有向量数据库")
        embedding_model = OllamaEmbeddings(model="qwen:0.5b")
        vectorstore = Chroma(
            persist_directory=VECTOR_DB_PATH,
            embedding_function=embedding_model
        )
        retriever = vectorstore.as_retriever(search_kwargs={"k": 2})

    # 构建 prompt
    template = """根据以下上下文回答问题:
    {context}

    问题: {question}
    """
    prompt = ChatPromptTemplate.from_template(template)

    # 初始化 LLM
    llm = ChatOllama(model="qwen:0.5b", temperature=0)

    # 构建 RAG 链
    rag_chain = (
            {"context": retriever, "question": RunnablePassthrough()}
            | prompt
            | llm
    )

    print(" RAG 系统初始化完成!")

def get_answer(question: str, context: str = "") -> str:
    """对外提供问答接口,支持上下文"""
    if rag_chain is None:
        raise Exception("RAG system not initialized. Call init_rag_system() first.")

    # 将上下文和问题组合在一起
    full_context = context + "\n问题: " + question

    try:
        response = rag_chain.invoke(full_context)
        return response.content.strip()
    except Exception as e:
        return f"回答生成失败: {str(e)}"
#api_server.py
from flask import Flask, request, jsonify
import threading

# 导入 RAG 模块
import rag_app

app = Flask(__name__)

# 全局锁和状态标记
init_lock = threading.Lock()
rag_initialized = False


def initialize_rag_system():
    """全局初始化 RAG 系统(线程安全)"""
    global rag_initialized
    with init_lock:
        if not rag_initialized:
            print(" 开始初始化 RAG 系统...")
            try:
                rag_app.init_rag_system()
                rag_initialized = True
                print(" RAG 系统初始化完成!")
            except Exception as e:
                print(f" RAG 初始化失败: {e}")
                raise


@app.route('/')
def home():
    if rag_initialized:
        return 'RAG API 已就绪!请使用 POST /rag_query 发送问题。'
    else:
        return 'RAG 系统正在初始化,请稍后...'

sessions = {}
@app.route('/rag_query', methods=['POST'])

def rag_query():
    global rag_initialized

    # 如果还没初始化,返回 503
    if not rag_initialized:
        return jsonify({
            "status": "error",
            "message": "RAG system is still initializing, please try later."
        }), 503

    data = request.get_json()
    if not data or "question" not in data:
        return jsonify({
            "status": "error",
            "message": "Missing 'question' in request body"
        }), 400

    # 获取会话 ID 和问题
    session_id = data.get("session_id", "default")
    question = data["question"]

    # 获取当前会话的历史上下文(如果有)
    context = sessions.get(session_id, "")

    print(f"收到问题 [{session_id}]: {question}")

    try:
        # 获取答案并更新会话历史
        answer = rag_app.get_answer(question, context=context)
        # 更新会话历史
        sessions[session_id] = context + "\n问题: " + question + "\n回答: " + answer

        print(f"回复问题 [{session_id}]: {answer}")
        return jsonify({
            "session_id": session_id,
            "question": question,
            "answer": answer,
            "status": "success"
        }), 200
    except Exception as e:
        return jsonify({
            "session_id": session_id,
            "question": question,
            "answer": "",
            "status": "error",
            "message": str(e)
        }), 500



if __name__ == '__main__':
    from waitress import serve

    print(" 启动 Flask 服务器...")

    # 在启动服务器前先初始化 RAG
    initialize_rag_system()
#端口可以自己改动
    print(" 服务启动中:http://0.0.0.0:8889")
    serve(app, host='0.0.0.0', port=8889)
# test_api.py
import json
import requests

# 要发送的数据
data = {
    "question": "核心产品",
    "id": "Q001"
}

try:
    response = requests.post('http://192.168.2.11:8889/rag_query', json=data)
    response.raise_for_status()
    result = response.json()
    print(" 请求成功!")
    print(" 响应内容:")
    print(json.dumps(result, indent=2, ensure_ascii=False))
except requests.exceptions.RequestException as e:
    print(f" 请求失败:{e}")

四、外网访问

正常而言,我们是构建了本地的,那么外网如何访问呢,这时候就需要用到内网穿透
因为端口没有那么多,普通用户可以使用一些内网穿透工具(很多工具虽然付费,但是会给一两条免费的通道使用)也够普通用户使用了
如果有公网ip的话,可以使用frp进行内网穿透(frp相对普通用户会更加麻烦一些),如果想了解可以看我上一篇文章。

ollama默认端口是11434,如果不加以RAG/Prompt那么构建端口为11434就可以
如果使用了RAG/Prompt等构建了新的api,那么端口就为你构建的端口,如我上文的8889端口,那是新的端口,使用内网穿透穿透此端口

总结

本文完整的给大家走了一遍流程,不过整体下来还是有些繁琐,但是在可以使用的那一瞬间满足感真的拉满,大家可以跟着此文一步一步顺一遍。但是之后此类方法感觉不会使用那么频繁,所以下期讲述本地部署dify和ragflow来调用这些模型,既能低代码使用,也能更快速构造想构造的工作流或聊天系统等

Logo

火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。

更多推荐