源代码 https://github.com/438083791/python-rag-demo

一、前言


1。什么是RAG?
RAG(Retrieval Augmented Generation)顾名思义,通过检索的方法来增强生成模型的能力
2.为什么需要RAG?

大模言模型(LLM)因为预训练的过程,加之本身是基于预测去生成内容的系统,导致它必然会有如下缺陷 知识时效性 推理局限性 专业领域盲区 幻觉问题

二、环境搭建

开发工具 Pycharm

Python 版本 3.10.11

安装Ollama ,安装教程请参考  Ollama+DeepSeek+AnythingLLM 搭建本地智能体

## 安装deepseek-r1:1.5b
ollama run deepseek-r1:1.5b

## 安装 embeddinggemma 嵌入模型
ollama pull embeddinggemma

2.1 创建项目

名称 langchain-rag-demo,Python version 选择Python 3.10


2.2 查看python 版本

点击左下角 Terminal ,输入

 python --version

## 显示Python 3.10.11

2.3项目结构

testOllamaRAG.py 文件

from langchain_community.document_loaders import TextLoader  # 加载 TXT 文档(支持其他格式,见下文扩展)
from langchain_ollama import OllamaLLM
from langchain_ollama import OllamaEmbeddings
from langchain_chroma import Chroma
from langchain_text_splitters import RecursiveCharacterTextSplitter  # 文档分割器
from langchain_core.prompts import ChatPromptTemplate  # 提示词模板
from langchain_core.runnables import RunnablePassthrough  # 流程透传
from langchain_core.output_parsers import StrOutputParser  # 输出解析器

# ===================== 1. 初始化模型(Ollama 本地模型)=====================
# 嵌入模型:embeddinggemma(用于生成文本向量)
embeddings = OllamaEmbeddings(
    model="embeddinggemma",  # 必须与本地拉取的模型名一致
    base_url="http://localhost:11434"  # Ollama 默认端口(无需修改,除非自定义)
)

# 大语言模型:用于生成最终回答(示例用 deepseek-r1:1.5b 等)
llm = OllamaLLM(
    model="deepseek-r1:1.5b",  # 确保已通过 `ollama run deepseek-r1:1.5b` 下载并启动
    temperature=0.1,  # 温度越低,回答越精准(0.1~0.3 适合事实性问答)
    base_url="http://localhost:11434"
)

# ===================== 2. 加载并处理文档(核心:分割为小片段)=====================
# 1. 加载本地 TXT 文档(替换为你的文档路径,支持多个文档)
loader = TextLoader("./docs/《三国演义》.txt")  # 示例:本地文档(如技术手册、知识库等)
documents = loader.load()

# 2. 分割文档:将长文档拆分为短片段(避免嵌入时丢失语义,提升检索精度)
text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=2000,  # 每个片段最大字符数(根据文档复杂度调整)
    chunk_overlap=200,  # 片段重叠字符数(保持上下文连贯性)
    length_function=len  # 按字符长度计算
)
split_documents = text_splitter.split_documents(documents)

# ===================== 3. 构建/加载 Chroma 向量库(核心替换)=====================
# Chroma 配置:本地存储路径、集合名称(可自定义)
CHROMA_DB_PATH = "./chroma_db"  # 向量库本地存储文件夹
COLLECTION_NAME = "knowledge_base"  # 集合名称(类似数据库的表)

# 方式1:新建 Chroma 向量库(首次运行,处理文档并写入)
vector_db = Chroma.from_documents(
    documents=split_documents,
    embedding=embeddings,
    persist_directory=CHROMA_DB_PATH,  # 本地持久化路径
    collection_name=COLLECTION_NAME,  # 集合名称(便于多知识库隔离)
    collection_metadata={"hnsw:space": "cosine"}  # 相似度计算方式(余弦相似度,适合嵌入向量)
)


# # 方式2:加载已保存的 Chroma 向量库(后续运行,跳过文档处理)
# vector_db = Chroma(
#     collection_name=COLLECTION_NAME,
#     embedding_function=embeddings,
#     persist_directory=CHROMA_DB_PATH
# )

# ===================== (可选)4. 动态添加新文档到 Chroma(增量更新)=====================
# 场景:后续新增文档,无需重建向量库,直接添加
def add_new_documents(new_doc_paths):
    """
    动态添加新文档到 Chroma 向量库
    new_doc_paths: 新文档路径列表(如 ["new_doc1.txt", "new_doc2.pdf"])
    """
    for path in new_doc_paths:
        # 加载新文档(根据后缀选择对应的 Loader)
        if path.endswith(".txt"):
            new_loader = TextLoader(path)
        elif path.endswith(".pdf"):
            from langchain_community.document_loaders import PyPDFLoader
            new_loader = PyPDFLoader(path)
        else:
            print(f"不支持的文档格式:{path}")
            continue

        new_docs = new_loader.load()
        new_split_docs = text_splitter.split_documents(new_docs)

        # 添加到 Chroma 向量库(自动增量更新,无需重建)
        vector_db.add_documents(documents=new_split_docs)
        print(f"已添加文档:{path}")


# 示例:添加新文档(实际使用时取消注释)
# add_new_documents(["new_document.txt", "tech_manual.pdf"])

# ===================== 5. 构建 RAG 检索链(与之前一致)=====================
# 检索器:从 Chroma 中检索最相关的 3 个文档片段
retriever = vector_db.as_retriever(
    search_kwargs={"k": 10}  # k=3 表示取 top3 相关片段
)

# 提示词模板:基于检索到的上下文回答,不编造信息
prompt = ChatPromptTemplate.from_template("""
你是专业的问答助手,必须严格基于以下上下文信息回答用户问题。
如果上下文没有相关内容,直接回复"根据知识库,未找到相关答案",禁止编造信息。

上下文信息:
{context}

用户问题:
{question}
""")

# 构建 RAG 链:检索 → 格式化上下文 → 生成回答
rag_chain = (
        {
            # 检索并拼接上下文(将多个文档片段合并为字符串)
            "context": retriever | (lambda docs: "\n\n".join([d.page_content for d in docs])),
            "question": RunnablePassthrough()  # 透传用户问题
        }
        | prompt  # 注入提示词和上下文
        | llm  # 本地 LLM 生成回答
        | StrOutputParser()  # 解析输出为字符串
)

# ===================== 6. 测试 RAG 效果 =====================
if __name__ == "__main__":
    # 测试问题(基于 《三国演义》.txt 中的内容)
    user_question = "诸葛亮是谁,简单介绍下他的功绩"

    # 执行 RAG 链
    result = rag_chain.invoke(user_question)

    # 输出结果
    print("=== RAG 回答 ===")
    print(result)

    # (可选)查看检索到的相关文档片段(调试用)
    retrieved_docs = retriever.invoke(user_question)
    print("\n=== 检索到的相关文档 ===")
    for i, doc in enumerate(retrieved_docs, 1):
        print(f"\n【片段 {i}】")
        print(doc.page_content)

《三国演义》.txt 下载地址

https://pan.baidu.com/s/1Jf6ya1ZrKdDyiDufQdzBdw?pwd=93s1

安装 langchain 相关包

 pip install 'langchain[all]' langchain-community langchain_ollama langchain_chroma langchain_text_splitters

2.4 运行Python程序

我们的提问

    # 测试问题(基于 《三国演义》.txt 中的内容)
    user_question = "诸葛亮是谁,简单介绍下他的功绩"

AI回答

=== RAG 回答 ===
诸葛亮是中国历史上蜀汉的重要人物,被誉为“东吴第一将”。他是西晋末年和北魏前期的重要谋士、政治家和军事家。以下是关于他的详细介绍:

### 一、基本信息
1. **出生与早逝**:诸葛亮出生于三国时期,具体年份不详,但据记载他早年生活在蜀汉。后主刘禅去世后,诸葛亮在北魏时期逐渐活跃于社会。

2. **主要事迹**:
   - **《出师表》**:他在《出师表》中详细描述了自己的战略思想和行动,展现了对国家治理的深刻思考。
   - **北伐**:他北伐蜀道、吴国等目标,展现了卓越的军事才能。
   - **北汉建立**:在魏汉战争期间,诸葛亮北伐,最终帮助北汉建立都城。

3. **政治与外交**:
   - 作为西晋末年的政治家,诸葛亮注重国家治理和对外关系。他主张“以天下为己任”,推动了地方自治制度的发展。
   - 在对外政策上,他主张“和平共处”理念,并积极推动对外文化交流。

### 二、主要功绩
1. **战略思想**:
   - 《出师表》中明确提出了“北伐有道,战时不息”的战略方针,强调灵活应变和长远规划。
   - 他在战争中的智慧和决策对后世影响深远,成为军事理论的重要来源。

2. **北伐行动**:
   - 在魏汉战争期间,诸葛亮北伐蜀道、吴国等目标,展现了卓越的军事才能。他的北伐行动不仅帮助北汉建立都城,还为三国时期的发展奠定了基础。

3. **北汉建立**:
   - 作为北魏的重要人物,诸葛亮在北汉建立中发挥了重要作用,推动了地方自治制度和行政管理的进步。

4. **后世影响**:
   - 诸葛亮的思想和行动对后世产生了深远的影响。他的军事智慧和政治策略被广泛传颂,成为中国历史上的典范。
   - 他在三国时期的地位和影响力,使得他成为了后人讨论的重要人物之一。

### 三、总结
诸葛亮是中国历史上蜀汉的重要人物,以其卓越的军事才能和深刻的政治智慧,为中国历史留下了宝贵的财富。他的《出师表》等著作对后世产生了深远的影响,成为中国政治思想的重要参考。

=== 检索到的相关文档 ===

【片段 1】
孔明受诏归府,唤诸将听令:前督部——镇北将军、领丞相司马、凉州刺史、都亭侯魏延;前军都督——领扶风太守张翼;牙门将——裨将军王平;后军领兵使——安汉将军、领建宁太守李恢,副将——定远将军、领汉中太守吕义;兼管运粮左军领兵使——平北将军、陈仓侯马岱,副将——飞卫将军廖化;右军领兵使——奋威将军、博阳亭侯马忠,抚戎将军、关内侯张嶷;行中军师——车骑大将军、都乡侯刘琰;中监军——扬武将军邓芝;中参军——安远将军马谡;前将军——都亭侯袁綝;左将军——高阳侯吴懿;右将军——

    玄都侯高翔;后将军——安乐侯吴班;领长史——绥军将军杨仪;前将军——征南将军刘巴;前护军——偏将军、汉城亭侯许允;左护军——笃信中郎将丁咸;右护军——偏将军刘敏;后护军——典军中郎将官雝;行参军——昭武中郎将胡济;行参军——谏议将军阎晏;行参军——偏将军爨习;行参军——裨将军杜义,武略中郎将杜祺,绥戎都尉盛勃;从事——武略中郎将樊岐;典军书记——樊建;丞相令史——

    董厥;帐前左护卫使——龙骧将军关兴;右护卫使——虎翼将军张苞。——以上一应官员,都随着平北大都督、丞相、武乡侯、领益州牧、知内外事诸葛亮。分拨已定,又檄李严等守川口以拒东吴。选定建兴五年春三月丙寅日,出师伐魏。

    忽帐下一老将,厉声而进曰:“我虽年迈,尚有廉颇之勇,马援之雄。此二古人皆不服老,何故不用我耶?”众视之,乃赵云也。孔明曰:“吾自平南回都,马孟起病故,吾甚惜之,以为折一臂也。今将军年纪已高,倘稍有参差,动摇一世英名,减却蜀中锐气。”云厉声曰:“吾自随先帝以来,临阵不退,遇敌则先。大丈夫得死于疆场者,幸也,吾何恨焉?愿为前部先锋!”孔明再三苦劝不住。云曰:“如不教我为先锋,就撞死于阶下!”孔明曰:“将军既要为先锋,须得一人同去。”言未尽,一人应曰:“某虽不才,愿助老将军先引一军前去破敌。”孔明视之,乃邓芝也。孔明大喜,即拨精兵五千。副将十员,随赵云、邓芝去讫。

    孔明出师,后主引百官送于北门外十里。孔明辞了后主,旌旗蔽野,戈戟如林,率军望汉中迤逦进发。却说边庭探知此事,报入洛阳。是日曹睿设朝,近臣奏曰:“边官报称:诸葛亮率领大兵三十余万,出屯汉中,令赵云、邓芝为前部先锋,引兵入境。”睿大惊,问群臣曰:“谁可为将,以退蜀兵?”忽一人应声而出曰:“臣父死于汉中,切齿之恨,未尝得报。今蜀兵犯境,臣愿引本部猛将,更乞陛下赐关西之兵,前往破蜀,上为国家效力,下报父仇,臣万死不恨!”众视之,乃夏侯渊之子夏侯楙也。楙字子休,其性最急,又最吝,自幼嗣与夏侯惇为子。后夏侯渊为黄忠所斩,曹操怜之,以女清河公主招楙为驸马,因此朝中钦敬。虽掌兵权,未尝临阵。当时自请出征,曹睿即命为大都督,调关西诸路军马前去迎敌。司徒王朗谏曰:“不可。夏侯驸马素不曾经战,今付以大任,非其所宜。更兼诸葛亮足智多谋,深通韧略,不可轻敌。”夏侯楙叱曰:“司徒莫非结连诸葛亮,欲为内应耶?吾自幼从父学习韬略,深通兵法。汝何欺我年幼?吾若不生擒诸葛亮,誓不回见天子!”王朗等皆不敢言。夏侯楙辞了魏主,星夜到长安,调关西诸路军马二十余万,来敌孔明。正是:欲秉白旄摩将士,却教黄吻掌兵权。未知胜负如何,且看下文分解。



正文 第九十二回 赵子龙力斩五将 诸葛亮智取三城

【片段 2】
维引众骑杀出重围,奔入大寨坚守,以待救兵。忽然流星马到,报说:“钟会打破阳安关,守将蒋舒归降,傅佥战死,汉中已属魏矣。乐城守将王含,汉城守将蒋斌,知汉中已失,亦开门而降。胡济抵敌不住,逃回成都求援去了。”维大惊,即传令拔寨。

    是夜兵至疆川口,前面一军摆开,为首魏将,乃是金城太守杨欣。维大怒,纵马交锋,只一合,杨欣败走,维拈弓射之,连射三箭皆不中。维转怒,自折其弓,挺枪赶来。战马前失,将维跌在地上。杨欣拨回马来杀姜维。维跃起身,一枪刺去,正中杨欣马脑。背后魏兵骤至,救欣去了。维骑上从马,欲待追时,忽报后面邓艾兵到。维首尾不能相顾,遂收兵要夺汉中。哨马报说:“雍州刺史诸葛绪已断了归路。”维乃据山险下寨。魏兵屯于阴平桥头。维进退无路,长叹曰:“天丧我也!”副将宁随曰:“魏兵虽断阴平桥头,雍州必然兵少,将军若从孔函谷,径取雍州,诸葛绪必撤阴平之兵救雍州,将军却引兵奔剑阁守之,则汉中可复矣。”维从之,即发兵入孔函谷,诈取雍州。细作报知诸葛绪。绪大惊曰:“雍州是吾合守之地,倘有疏失,朝廷必然问罪。”急撤大兵从南路去救雍州,只留一枝兵守桥头。姜维入北道,约行三十里,料知魏兵起行,乃勒回兵,后队作前队,径到桥头,果然魏兵大队已去,只有些小兵把桥,被维一阵杀散,尽烧其寨栅。诸葛绪听知桥头火起,复引兵回,姜维兵已过半日了,因此不敢追赶。却说姜维引兵过了桥头,正行之间,前面一军来到,乃左将军张翼、右将军廖化也。维问之,翼曰:“黄皓听信师巫之言,不肯发兵。翼闻汉中已危,自起兵来,时阳安关已被钟会所取。今闻将军受困,特来接应。”遂合兵一处,前赴白水关。化曰:“今四面受敌,粮道不通,不如退守剑阁,再作良图。”维疑虑未决。忽报钟会、邓艾分兵十余路杀来。维欲与翼、化分兵迎之。化曰:“白水地狭路多,非争战之所,不如且退去救剑阁可也;若剑阁一失,是绝路矣。”维从之,遂引兵来投剑阁。将近关前,忽然鼓角齐鸣,喊声大起,旌旗遍竖,一枝军把住关口。正是:汉中险峻已无有,剑阁风波又忽生。未知何处之兵,且看下文分解。



正文 第一百十七回 邓士载偷度阴平 诸葛瞻战死绵竹

    却说辅国大将军董厥,闻魏兵十余路入境,乃引二万兵守住剑阁;当日望尘头大起,疑是魏兵,急引军把住关口。董厥自临军前视之,乃姜维、廖化、张翼也。厥大喜,接入关上,礼毕,哭诉后主黄皓之事。维曰:“公勿忧虑。若有维在,必不容魏来吞蜀也。且守剑阁,徐图退敌之计。”厥曰:“此关虽然可守,争奈成都无人;倘为敌人所袭,大势瓦解矣。”维曰:“成都山险地峻,非可易取,不必忧也。”正言间,忽报诸葛绪领兵杀至关下,维大怒,急引五千兵杀下关来,直撞入魏阵中,左冲右突,杀得诸葛绪大败而走,退数十里下寨,魏军死者无数。蜀兵抢了许多马匹器械,维收兵回关。

    却说钟会离剑阁二十里下寨,诸葛绪自来伏罪。会怒曰:“吾令汝守把阴平桥头,以断姜维归路,如何失了!今又不得吾令,擅自进兵,以致此败!”绪曰:“维诡计多端,诈取雍州;绪恐雍州有失,引兵去救,维乘机走脱;绪因赶至关下,不想又为所败。”会大怒,叱令斩之。监军卫瓘曰:“绪虽有罪,乃邓征西所督之人;不争将军杀之,恐伤和气。”会曰:“吾奉天子明诏、晋公钧命,特来伐蜀。便是邓艾有罪,亦当斩之!”众皆力劝。会乃将诸葛绪用槛车载赴洛阳,任晋公发落;随将绪所领之兵,收在部下调遣。

    有人报与邓艾。艾大怒曰:“吾与汝官品一般,吾久镇边疆,于国多劳,汝安敢妄自尊大耶!”子邓忠劝曰:“小不忍则乱大谋,父亲若与他不睦,必误国家大事。望且容忍之。”艾从其言。然毕竟心中怀怒,乃引十数骑来见钟会。会闻艾至,便问左右:“艾引多少军来?”左右答曰:“只有十数骑。”会乃令帐上帐下列武士数百人。

    艾下马入见。会接入帐礼毕。艾见军容甚肃,心中不安,乃以言挑之曰:“将军得了汉中,乃朝廷之大幸也,可定策早取剑阁。”会曰:“将军明见若何?”艾再三推称无能。会固问之。艾答曰:“以愚意度之,可引一军从阴平小路出汉中德阳亭,用奇兵径取成都,姜维必撤兵来救,将军乘虚就取剑阁,可获全功。”会大喜曰:“将军此计甚妙!可即引兵去。吾在此专候捷音!”二人饮酒相别。会回本帐与诸将曰:“人皆谓邓艾有能。今日观之,乃庸才耳!”众问其故。会曰:“阴平小路,皆高山峻岭,若蜀以百余人守其险要,断其归路,则邓艾之兵皆饿死矣。吾只以正道而行,何愁蜀地不破乎!”遂置云梯炮架,只打剑阁关。

【片段 3】
孙桓折了李异、谢旌、谭雄等许多将士,力穷势孤,不能抵敌,即差人回吴求救。蜀将张南、冯习谓吴班曰:“目今吴兵势败,正好乘虚劫寨。”班曰:“孙桓虽然折了许多将士,朱然水军现今结营江上,未曾损折。今日若去劫寨,倘水军上岸,断我归路,如之奈何?”南曰:“此事至易:可教关、张二将军,各引五千军伏于山谷中;如朱然来救,左右两军齐出夹攻,必然取胜。”班曰:“不如先使小卒诈作降兵,却将劫寨事告与朱然;然见火起,必来救应,却令伏兵击之,则大事济矣。”冯习等大喜,遂依计而行。

    却说朱然听知孙桓损兵折将,正欲来救,忽伏路军引几个小卒上船投降。然问之,小卒曰:“我等是冯习帐下士卒,因赏罚不明,待来投降,就报机密。”然曰:“所报何事?”小卒曰:“今晚冯习乘虚要劫孙将军营寨,约定举火为号。”朱然听毕,即使人报知孙桓。报事人行至半途,被关兴杀了。朱然一面商议,欲引兵去救应孙桓。部将崔禹曰:“小卒之言,未可深信。倘有疏虞,水陆二军尽皆休矣。将军只宜稳守水寨,某愿替将军一行。”然从之,遂令崔禹引一万军前去。是夜,冯习、张南、吴班分兵三路,直杀入孙桓寨中,四面火起,吴兵大乱,寻路奔走。

    且说崔禹正行之间,忽见火起,急催兵前进。刚才转过山来,忽山谷中鼓声大震:左边关兴,右边张苞,两路夹攻。崔禹大惊,方欲奔走,正遇张苞;交马只一合,被苞生擒而回。朱然听知危急,将船往下水退五六十里去了。孙桓引败军逃走,问部将曰:“前去何处城坚粮广?”部将曰:“此去正北彝陵城,可以屯兵。”桓引败军急望彝陵而走。方进得城,吴班等追至,将城四面围定。关兴、张苞等解崔禹到秭归来。先主大喜,传旨将崔禹斩却,大赏三军。自此威风震动,江南诸将无不胆寒。

    却说孙桓令人求救于吴王,吴王大惊,即召文武商议曰:“今孙桓受困于彝陵,朱然大败于江中,蜀兵势大,如之奈何?”张昭奏曰:“今诸将虽多物故,然尚有十余人,何虑于刘备?可命韩当为正将,周泰为副将,潘璋为先锋,凌统为合后,甘宁为救应,起兵十万拒之。”权依所奏,即命诸将速行。此时甘宁已患痢疾,带病从征。

    却说先主从巫峡建平起,直接彝陵界分,七十余里,连结四十余寨;见关兴、张苞屡立大功,叹曰:“昔日从朕诸将,皆老迈无用矣;复有二侄如此英雄,朕何虑孙权乎!”正言间,忽报韩当、周泰领兵来到。先主方欲遣将迎敌,近臣奏曰:“老将黄忠,引五六人投东吴去了。”先主笑曰:“黄汉升非反叛之人也;因朕失口误言老者无用,彼必不服老,故奋力去相持矣。”即召关兴、张苞曰:“黄汉升此去必然有失。贤侄休辞劳苦,可去相助。略有微功,便可令回,勿使有失。”二小将拜辞先主,引本部军来助黄忠。正是:老臣素矢忠君志,年少能成报国功。未知黄忠此去如何,且看下文分解。



正文 第八十三回 战猇亭先主得仇人 守江口书生拜大将

    却说章武二年春正月,武威后将军黄忠随先主伐吴;忽闻先主言老将无用,即提刀上马,引亲随五六人,径到彝陵营中。吴班与张南、冯习接入,问曰:“老将军此来,有何事故?”忠曰:“吾自长沙跟天子到今,多负勤劳。今虽七旬有余,尚食肉十斤,臂开二石之弓,能乘千里之马,未足为老。昨日主上言吾等老迈无用,故来此与东吴交锋,看吾斩将,老也不老!”正言间,忽报吴兵前部已到,哨马临营。忠奋然而起,出帐上马。冯习等劝曰:“老将军且休轻进。”忠不听,纵马而去。吴班令冯习引兵助战。忠在吴军阵前,勒马横刀,单搦先锋潘璋交战。璋引部将史迹出马。迹欺忠年老,挺枪出战;斗不三合,被忠一刀斩于马下。潘璋大怒,挥关公使的青龙刀,来战黄忠。交马数合,不分胜负。忠奋力恶战,璋料敌不过,拨马便走。忠乘势追杀,全胜而回。路逢关兴、张苞。兴曰:“我等奉圣旨来助老将军;既已立了功,速请回营。”忠不听。次日,潘璋又来搦战。黄忠奋然上马。兴、苞二人要助战,忠不从;吴班要助战,忠亦不从;只自引五千军出迎。战不数合,璋拖刀便走。忠纵马追之,厉声大叫曰:“贼将休走!吾今为关公报仇!”追至三十余里,四面喊声大震,伏兵齐出:右边周泰,左边韩当,前有潘璋,后有凌统,把黄忠困在垓心。忽然狂风大起,忠急退时,山坡上马忠引一军出,一箭射中黄忠肩窝,险些儿落马。吴兵见忠中箭,一齐来攻,忽后面喊声大起,两路军杀来,吴兵溃散,救出黄忠,乃关兴、张苞也。二小将保送黄忠径到御前营中。忠年老血衰,箭疮痛裂,病甚沉重。先主御驾自来看视,抚其背曰:“令老将军中伤,朕之过也!”忠曰:“臣乃一武夫耳,幸遇陛下。臣今年七十有五,寿亦足矣。望陛下善保龙体,以图中原!”言讫,不省人事。是夜殒于御营。后人有诗叹曰:“老将说黄忠,收川立大功。重披金锁甲,双挽铁胎弓。胆气惊河北,威名镇蜀中。临亡头似雪,犹自显英雄。”

【片段 4】
邓艾取了江油,遂接阴平小路诸军,皆到江油取齐,径来攻涪城。部将田续曰:“我军涉险而来,甚是劳顿,且当休养数日,然后进兵。”艾大怒曰:“兵贵神速,汝敢乱我军心耶!”喝令左右推出斩之。众将苦告方免。艾自驱兵至涪城。城内官吏军民疑从天降,尽皆投降。

    蜀人飞报入成都。后主闻知,慌召黄皓问之。皓奏曰:“此诈传耳。神人必不肯误陛下也。”后主又宣师婆问时,却不知何处去了。此时远近告急表文,一似雪片,往来使者,联络不绝。后主设朝计议,多官面面相觑,并无一言。郤正出班奏曰:“事已急矣!陛下可宣武侯之子商议退兵之策。”原来武侯之子诸葛瞻,字思远。其母黄氏,即黄承彦之女也。母貌甚陋,而有奇才:上通天文,下察地理;凡韬略遁甲诸书,无所不晓。武侯在南阳时,闻其贤,求以为室。武侯之学,夫人多所赞助焉。及武侯死后,夫人寻逝,临终遗教,惟以忠孝勉其子瞻。瞻自幼聪敏,尚后主女,为驸马都尉。后袭父武乡侯之爵。景耀四年,迁行军护卫将军。时为黄皓用事,故托病不出。当下后主从郤正之言,即时连发三诏,召瞻至殿下。后主泣诉曰:“邓艾兵已屯涪城,成都危矣。卿看先君之面,救朕之命!”瞻亦泣奏曰:“臣父子蒙先帝厚恩、陛下殊遇,虽肝脑涂地,不能补报。愿陛下尽发成都之兵,与臣领去决一死战。”后主即拨成都兵将七万与瞻。瞻辞了后主,整顿军马,聚集诸将问曰:“谁敢为先锋?”言未讫,一少年将出曰:“父亲既掌大权,儿愿为先锋。”众视之,乃瞻长子诸葛尚也。尚时年一十九岁。博览兵书。多习武艺。瞻大喜,遂命尚为先锋。是日,大军离了成都,来迎魏兵。

    却说邓艾得马邈献地理图一本,备写涪城至成都三百六十里山川道路,阔狭险峻,一一分明。艾看毕,大惊曰:“若只守涪城,倘被蜀人据住前山,何能成功耶?如迁延日久,姜维兵到,我军危矣。”速唤师纂并子邓忠,分付曰:“汝等可引一军,星夜径去绵竹,以拒蜀兵。吾随后便至。切不可怠缓。若纵他先据了险要,决斩汝首!”

    师、邓二人引兵将至锦竹,早遇蜀兵。两军各布成阵。师、邓二人勒马于门旗下,只见蜀兵列成八阵。三鼕鼓罢,门旗两分,数十员将簇拥一辆四轮车,车上端坐一人:纶巾羽扇,鹤氅方裾。车傍展开一面黄旗,上书:“汉丞相诸葛武侯”。?得师、邓二人汗流遍身,回顾军士曰:“原来孔明尚在,我等休矣!”急勒兵回时,蜀兵掩杀将来,魏兵大败而走。蜀兵掩杀二十余里,遇见邓艾援兵接应。两家各自收兵。艾升帐而坐,唤师纂、邓忠责之曰:“汝二人不战而退,何也?”忠曰:“但见蜀阵中诸葛孔明领兵,因此奔还。”艾怒曰:“纵使孔明更生,我何惧哉!汝等轻退,以致于败,宜速斩以正军法!”众皆苦劝,艾方息怒。令人哨探,回说孔明之子诸葛瞻为大将,瞻之子诸葛尚为先锋。——车上坐者乃木刻孔明遗像也。

    艾闻之,谓师纂、邓忠曰:“成败之机,在此一举。汝二人再不取胜,必当斩首!”师、邓二人又引一万兵来战。诸葛尚匹马单枪,抖擞精神,战退二人。诸葛瞻指挥两掖兵冲出,直撞入魏阵中,左冲右突,往来杀有数十番,魏兵大败,死者不计其数。师纂、邓忠中伤而逃。瞻驱士马随后掩杀二十余里,扎营相拒。师纂、邓忠回见邓艾,艾见二人俱伤,未便加责,乃与众将商议曰:“蜀有诸葛瞻善继父志,两番杀吾万余人马,今若不速破,后必为祸。”监军丘本曰:“何不作一书以诱之?”艾从其言,遂作书一封,遣使送人蜀寨。守门将引至帐下,呈上其书。瞻拆封视之。书曰:“征西将军邓艾,致书于行军护卫将军诸葛思远麾下:切观近代贤才,未有如公之尊父也。昔自出茅庐,一言已分三国,扫平荆、益,遂成霸业,古今鲜有及者;后六出祁山,非其智力不足,乃天数耳。今后主昏弱,王气已终,艾奉天子之命,以重兵伐蜀,已皆得其地矣。成都危在旦夕,公何不应天顺人,仗义来归?艾当表公为琅琊王,以光耀祖宗,决不虚言。幸存照鉴。”瞻看毕,勃然大怒,扯碎其书,叱武士立斩来使,令从者持首级回魏营见邓艾。艾大怒,即欲出战。丘本谏曰:“将军不可轻出,当用奇兵胜之。”艾从其言,遂令天水太守王颀、陇西太守牵弘,伏两军于后,艾自引兵而来。此时诸葛瞻正欲搦战,忽报邓艾自引兵到。瞻大怒,即引兵出,径杀入魏阵中。邓艾败走,瞻随后掩杀将来。忽然两下伏兵杀出。蜀兵大败,退入绵竹。艾令围之。于是魏兵一齐呐喊,将绵竹围的铁桶相似。诸葛瞻在城中,见事势已迫,乃令彭和赍书杀出,往东吴求救。和至东吴,见了吴主孙休,呈上告急之书。吴主看罢,与群臣计议曰:“既蜀中危急,孤岂可坐视不救。”即令考将丁奉为主帅,丁封、孙异为副将,率兵五万,前往救蜀。丁奉领旨出师,分拨丁封、孙异引兵二万向沔中而进,自率兵三万向寿春而进:分兵三路来援。

【片段 5】
孔明正在营中忧闷,忽报:“东边救兵到了,旗上书:‘魏先锋大将王双’。”孔明问曰:“谁可迎之?”魏延出曰:“某愿往。”孔明曰:“汝乃先锋大将,未可轻出。”又问:“谁敢迎之?”裨将谢雄应声而出。孔明与三千军去了。孔明又问曰:“谁敢再去?”裨将龚起应声要去。孔明亦与三千兵去了。孔明恐城内郝昭引兵冲出,乃把人马退二十里下寨。

    却说谢雄引军前行,正遇王双;战不三合,被双一刀劈死。蜀兵败走,双随后赶来。龚起接着,交马只三合,办被双所斩。败兵回报孔明。孔明大惊,忙令廖化、王平、张嶷三人出迎。两阵对圆,张嶷出马,王平、廖化压住阵角。王双纵马来与张嶷交马,数合不分胜负。双诈败便走,嶷随后赶去。王平见张嶷中计,忙叫曰:“休赶!”嶷急回马时,王双流星锤早到,正中其背。巍伏鞍而走,双回马赶来。王平、廖化截住,救得张嶷回阵。王双驱兵大杀一阵,蜀兵折伤甚多。巍吐血数口,回见孔明,说:“王双英雄无敌;如今将二万兵就陈仓城外下寨,四围立起排栅,筑起重城,深挖壕堑,守御甚严。”孔明见折二将,张嶷又被打伤,即唤姜维曰:“陈仓道口这条路不可行。别求何策?”维曰:“陈仓城池坚固,郝昭守御甚密,又得王双相助,实不可取。不若令一大将,依山傍水,下寨固守;再令良将守把要道,以防街亭之攻;却统大军去袭祁山,某却如此如此用计,可捉曹真也。”孔明从其言,即令王平,李恢,引二枝兵守街亭小路;魏延引一军守陈仓口。马岱为先锋,关兴、张苞为前后救应使,从小径出斜谷望祁山进发。却说曹真因思前番被司马懿夺了功劳,因此到洛阳分调郭淮、孙礼东西守把;又听的陈仓告急,已令王双去救。闻知王双斩将立功,大喜,乃令中护军大将费耀,权摄前部总督,诸将各自守把隘口。忽报山谷中捉得细作来见。曹真令押入,跪于帐前。其人告曰:“小人不是奸细,有机密来见都督,误被伏路军捉来,乞退左右。”真乃教去其缚,左右暂退。其人曰:“小人乃姜伯约心腹人也。蒙本官遣送密书。”真曰:“书安在?”其人于贴肉衣内取出呈上。真拆视曰:“罪将姜维百拜,书呈大都督曹麾下:维念世食魏禄,忝守边城;叨窃厚恩,无门补报。昨日误遭诸葛亮之计,陷身于巅崖之中。思念旧国,何日忘之!今幸蜀兵西出,诸葛亮甚不相疑。赖都督亲提大兵而来:如遇敌人,可以诈败;维当在后,以举火为号,先烧蜀人粮草,却以大兵翻身掩之,则诸葛亮可擒也。非敢立功报国,实欲自赎前罪。倘蒙照察,速赐来命。”曹真看毕,大喜曰:“天使吾成功也!”遂重赏来人,便令回报,依期会合。真唤费耀商议曰:“今姜维暗献密书,令吾如此如此。”耀曰:“诸葛亮多谋,姜维智广,或者是诸葛亮所使,恐其中有诈。”真曰:“他原是魏人,不得已而降蜀,又何疑乎?”耀曰:“都督不可轻去,只守定本寨。某愿引一军接应姜维。如成,功尽归都督;倘有奸计,某自支当。”真大喜,遂令费耀引五万兵,望斜谷而进。行了两三程,屯下军马,令人哨探。当日申时分,回报:“斜谷道中,有蜀兵来也。”耀忙催兵进。蜀兵未及交战先退。耀引兵追之,蜀兵又来。方欲对阵,蜀兵又退:如此者三次,俄延至次日申时分。魏军一日一夜,不曾敢歇,只恐蜀兵攻击。方欲屯军造饭,忽然四面喊声大震,鼓角齐鸣,蜀兵漫山遍野而来。门旗开处,闪出一辆四轮车,孔明端坐其中,令人请魏军主将答话。耀纵马而出,遥见孔明,心中暗喜,回顾左右曰:“如蜀兵掩至,便退后走。若见山后火起,却回身杀去,自有兵来相应。”分付毕,跃马出呼曰:“前者败将,今何敢又来!”孔明曰:“唤汝曹真来答话!”耀骂曰:“曹都督乃金枝玉叶,安肯与反贼相见耶!”孔明大怒,把羽扇一招,左有马岱,右有张嶷,两路兵冲出。魏兵便退。行不到三十里,望见蜀兵背后火起,喊声不绝。费耀只道号火,便回身杀来。蜀兵齐退。耀提刀在前,只望喊处追赶。将次近火,山路中鼓角喧天、喊声震地,两军杀出:左有关兴,右有张苞。山上矢石如雨,往下射来。魏兵大败。费耀知是中计,急退军望山谷中而走,人马困乏。背后关兴引生力军赶来,魏兵自相践踏及落涧身死者,不知其数。

    耀逃命而走,正遇山坡口一彪军,乃是姜维。耀大骂曰:“反贼无信!吾不幸误中汝奸计也!”维笑曰:“吾欲擒曹真,误赚汝矣!速下马受降!”耀骤马夺路,望山谷中而走。忽见谷口火光冲天,背后追兵又至。耀自刎身死,余众尽降。孔明连夜驱兵,直出祁山前下寨,收住军马,重赏姜维。维曰:“某恨不得杀曹真也!”孔明亦曰:“可惜大计小用矣。”

    却说曹真听知折了费耀,悔之不及,遂与郭淮商议退兵之策。于是孙礼、辛毗星夜具表申奏魏主,言蜀兵又出祁山,曹真损兵折将,势甚危急。睿大惊,即召司马懿入内曰:“曹真损兵折将,蜀兵又出祁山。卿有何策,可以退之?”懿曰:“臣已有退诸葛亮之计。不用魏军扬武耀威,蜀兵自然走矣。”正是:已见子丹无胜术,全凭仲达有良谋。未知其计如何,且看下文分解。

【片段 6】
却说赵云在营中,看看等到午时,不见忠回,急忙披挂上马,引三千军向前接应;临行,谓张翼曰:“汝可坚守营寨。两壁厢多设弓弩,以为准备。”翼连声应诺。云挺枪骤马直杀往前去。迎头一将拦路,乃文聘部将慕容烈也,拍马舞刀来迎赵云;被云手起一枪刺死。曹兵败走。云直杀入重围,又一枝兵截住;为首乃魏将焦炳。云喝问曰:“蜀兵何在?”炳曰:“已杀尽矣!”云大怒,骤马一枪,又刺死焦炳。杀散余兵,直至北山之下,见张郃、徐晃两人围住黄忠,军士被困多时。云大喝一声,挺枪骤马,杀入重围,左冲右突,如入无人之境。那枪浑身上下,若舞梨花;遍体纷纷,如飘瑞雪。张郃、徐晃心惊胆战,不敢迎敌。云救出黄忠,且战且走;所到之处,无人敢阻。操于高处望见,惊问众将曰:“此将何人也?”有识者告曰:“此乃常山赵子龙也。”操曰:“昔日当阳长坂英雄尚在!”急传令曰:“所到之处,不许轻敌。”赵云救了黄忠,杀透重围,有军士指曰:“东南上围的,必是副将张著。”云不回本寨,遂望东南杀来。所到之处,但见“常山赵云”四字旗号,曾在当阳长坂知其勇者,互相传说,尽皆逃窜。云又救了张著。曹操见云东冲西突,所向无前,莫敢迎敌,救了黄忠,又救了张著,奋然大怒,自领左右将士来赶赵云。云已杀回本寨。部将张翼接着,望见后面尘起,知是曹兵追来,即谓云曰:“追兵渐近,可令军士闭上寨门,上敌楼防护。”云喝曰:“休闭寨门!汝岂不知吾昔在当阳长坂时,单枪匹马,觑曹兵八十三万如草芥!今有军有将,又何惧哉!”遂拨弓弩手于寨外壕中埋伏;将营内旗枪,尽皆倒偃,金鼓不鸣。云匹马单枪,立于营门之外。却说张郃、徐晃领兵追至蜀寨,天色已暮;见寨中偃旗息鼓,又见赵云匹马单枪,立于营外,寨门大开,二将不敢前进。正疑之间,曹操亲到,急催督众军向前。众军听令,大喊一声,杀奔营前;见赵云全然不动,曹兵翻身就回。赵云把枪一招,壕中弓弩齐发。时天色昏黑,正不知蜀兵多少。操先拨回马走。只听得后面喊声大震,鼓角齐鸣,蜀兵赶来。曹兵自相践踏,拥到汉水河边,落水死者,不知其数。赵云、黄忠、张著各引兵一枝,追杀甚急。操正奔走间,忽刘封、孟达率二枝兵,从米仓山路杀来,放火烧粮草。操弃了北山粮草,忙回南郑。徐晃、张郃扎脚不住,亦弃本寨而走。赵云占了曹寨,黄忠夺了粮草,汉水所得军器无数,大获胜捷,差人去报玄德。玄德遂同孔明前至汉水,问赵云的部卒曰:“子龙如何厮杀?”军士将子龙救黄忠、拒汉水之事,细述一遍。玄德大喜,看了山前山后险峻之路,欣然谓孔明曰:“子龙一身都是胆也!”后人有诗赞曰:“昔日战长坂,威风犹未减。突阵显英雄,被围施勇敢。鬼哭与神号,天惊并地惨。常山赵子龙,一身都是胆!”于是玄德号子龙为虎威将军,大劳将士,欢宴至晚。忽报曹操复遣大军从斜谷小路而进,来取汉水。玄德笑曰:“操此来无能为也。我料必得汉水矣。”乃率兵于汉水之西以迎之。曹操命徐晃为先锋,前来决战。帐前一人出曰:“某深知地理,愿助徐将军同去破蜀。”操视之,乃巴西宕渠人也,姓王,名平,字子均;现充牙门将军。操大喜,遂命王平为副先锋,相助徐晃。操屯兵于定军山北。徐晃、王平引军至汉水,晃令前军渡水列阵。平曰:“军若渡水,倘要急退,如之奈何?”晃曰:“昔韩信背水为阵,所谓致之死地而后生也。”平曰:“不然。昔者韩信料敌人无谋而用此计;今将军能料赵云、黄忠之意否?”晃曰:“汝可引步军拒敌,看我引马军破之。”遂令搭起浮桥,随即过河来战蜀兵。正是:魏人妄意宗韩信,蜀相那知是子房。未知胜负如何,且看下文分解。



正文 第七十二回 诸葛亮智取汉中 曹阿瞒兵退斜谷

【片段 7】
司马师见毋丘俭军退,聚多官商议。尚书傅嘏曰:“今俭兵退者,忧吴人袭寿春也。必回项城分兵拒守。将军可令一军取乐嘉城,一军取项城,一军取寿春,则淮南之卒必退矣。兖州刺史邓艾,足智多谋;若领兵径取乐嘉,更以重兵应之,破贼不难也。”师从之,急遣使持檄文,教邓艾起兖州之兵破乐嘉城。师随后引兵到彼会合。

    却说毋丘俭在项城,不时差人去乐嘉城哨探,只恐有兵来。请文钦到营共议,钦曰:“都督勿忧。我与拙子文鸯,只消五千兵,取保乐嘉城。”俭大喜。钦父子引五千兵投乐嘉来。前军报说:“乐嘉城西,皆是魏兵,约有万余。遥望中军,白旄黄钺,皂盖朱幡,簇拥虎帐,内竖一面锦绣帅字旗,必是司马师也,安立营寨,尚未完备。”时文鸯悬鞭立于父侧,闻知此语,乃告父曰:“趁彼营寨未成,可分兵两路,左右击之,可全胜也。”钦曰:“何时可去?”鸯曰:“今夜黄昏,父引二千五百兵,从城南杀来;儿引二千五百兵,从城北杀来:三更时分,要在魏寨会合。”钦从之,当晚分兵两路。且说文鸯年方十八岁,身长八尺,全装惯甲,腰悬钢鞭,绰枪上马,遥望魏寨而进。是夜,司马师兵到乐嘉,立下营寨,等邓艾未至。师为眼下新割肉瘤,疮口疼痛,卧于帐中,令数百甲士环立护卫。三更时分,忽然寨内喊声大震,人马大乱。师急问之,人报曰:“一军从寨北斩围直入,为首一将,勇不可当!”师大惊,心如火烈,眼珠从肉瘤疮口内迸出,血流遍地,疼痛难当;又恐有乱军心,只咬被头而忍,被皆咬烂。原来文鸯军马先到,一拥而进,在寨中左冲右突;所到之处,人不敢当,有相拒者,枪搠鞭打,无不被杀。鸯只望父到,以为外应,并不见来。数番杀到中军,皆被弓弩射回。鸯直杀到天明,只听得北边鼓角喧天。鸯回顾从者曰:“父亲不在南面为应,却从北至,何也?”鸯纵马看时,只见一军行如猛风,为首一将,乃邓艾也,跃马横刀,大呼曰:“反贼休走!”鸯大怒,挺枪迎之。战有五十合,不分胜败。正斗间,魏兵大进,前后夹攻,鸯部下兵乃各自逃散,只文鸯单人独马,冲开魏兵,望南而走。背后数百员魏将,抖擞精神,骤马追来;将至乐嘉桥边,看看赶上。鸯忽然勒回马大喝一声,直冲入魏将阵中来;钢鞭起处,纷纷落马,各各倒退。鸯复缓缓而行。魏将聚在一处,惊讶曰:“此人尚敢退我等之众耶!可并力追之!”于是魏将百员,复来追赶。鸯勃然大怒曰:“鼠辈何不惜命也!”提鞭拨马,杀入魏将丛中,用鞭打死数人,复回马缓辔而行。魏将连追四五番,皆被文鸯一人杀退。后人有诗曰:“长坂当年独拒曹,子龙从此显英豪。乐嘉城内争锋处,又见文鸯胆气高。”原来文钦被山路崎岖,迷入谷中,行了半夜,比及寻路而出,天色已晓,文鸯人马不知所向,只见魏兵大胜。钦不战而退。魏兵乘势追杀,钦引兵望寿春而走。

    却说魏殿中校尉尹大目,乃曹爽心腹之人,因爽被司马懿谋杀,故事司马师,常有杀师报爽之心;又素与文钦交厚。今见师眼瘤突出,不能动止,乃入帐告曰:“文钦本无反心,今被毋丘俭逼迫,以致如此。某去说之,必然来降。”师从之。大目顶盔惯甲,乘马来赶文钦;看看赶上,乃高声大叫曰:“文刺史见尹大目么?”钦回头视之,大目除盔放于鞍鞒之前,以鞭指曰:“文刺史何不忍耐数日也?”此是大目知师将亡,故来留钦。钦不解其意,厉声大骂,便欲开弓射之。大目大哭而回。钦收聚人马奔寿春时,已被诸葛诞引兵取了;欲复回项城时,胡遵、王基、邓艾三路兵皆到。钦见势危,遂投东吴孙峻去了。却说毋丘俭在项城内,听知寿春已失,文钦势败,城外三路兵到,俭遂尽撤城中之兵出战。正与邓艾相遇,俭令葛雍出马,与艾交锋,不一合,被艾一刀斩之,引兵杀过阵来。毋丘俭死战相拒。江淮兵大乱。胡遵、王基引兵四面夹攻。毋丘俭敌不住,引十余骑夺路而走。前至慎县城下,县令宋白开门接入,设席待之。俭大醉,被宋白令人杀了,将头献与魏兵。于是淮南平定。司马师卧病不起,唤诸葛诞入帐,赐以印绶,加为镇东大将军,都督扬州诸路军马;一面班师回许昌。师目痛不止,每夜只见李丰、张缉、夏侯玄三人立于榻前。师心神恍惚,自料难保,遂令人往洛阳取司马昭到。昭哭拜于床下。师遗言曰:“吾今权重,虽欲卸肩,不可得也。汝继我为之,大事切不可轻托他人,自取灭族之祸。”言讫,以印绶付之,泪流满面。昭急欲问时,师大叫一声,眼睛迸出而死。时正元二年二月也。于是司马昭发丧,申奏魏主曹髦。

【片段 8】
却说徐晃正坐帐中,忽报魏王使至。晃接入问之,使曰:“今魏王引兵,已过洛阳;令将军急战关公,以解樊城之困。”正说间,探马报说:“关平屯兵在偃城,廖化屯兵在四冢:前后一十二个寨栅,连络不绝。”晃即差副将徐商、吕建假着徐晃旗号,前赴偃城与关平交战。晃却自引精兵五百,循沔水去袭偃城之后。且说关平闻徐晃自引兵至,遂提本部兵迎敌。两阵对圆,关平出马,与徐商交锋,只三合,商大败而走;吕建出战,五六合亦败走。平乘胜追杀二十余里,忽报城中火起。平知中计,急勒兵回救偃城。正遇一彪军摆开,徐晃立马在门旗下,高叫曰:“关平贤侄,好不知死!汝荆州已被东吴夺了,犹然在此狂为!”平大怒,纵马轮刀,直取徐晃;不三四合,三军喊叫,偃城中火光大起。平不敢恋战,杀条大路,径奔四冢寨来。廖化接着。化曰:“人言荆州已被吕蒙袭了,军心惊慌,如之奈何?”平曰:“此必讹言也。军士再言者斩之。”

    忽流星马到,报说正北第一屯被徐晃领兵攻打。平曰:“若第一屯有失,诸营岂得安宁?此间皆靠沔水,贼兵不敢到此。吾与汝同去救第一屯。”廖化唤部将分付曰:“汝等坚守营寨,如有贼到,即便举火。”部将曰:“四冢寨鹿角十重,虽飞鸟亦不能入,何虑贼兵!”于是关平、廖化尽起四冢寨精兵,奔至第一屯住扎。关平看见魏兵屯于浅山之上,谓廖化曰:“徐晃屯兵,不得地利,今夜可引兵劫寨。”化曰:“将军可分兵一半前去,某当谨守本寨。”

    是夜,关平引一枝兵杀入魏寨,不见一人。平知是计,火速退时,左边徐商,右边吕建,两下夹攻。平大败回营,魏兵乘势追杀前来,四面围住。关平、廖化支持不住,弃了第一屯,径投四冢寨来。早望见寨中火起。急到寨前,只见皆是魏兵旗号。关平等退兵,忙奔樊城大路而走。前面一军拦住,为首大将,乃是徐晃也。平、化二人奋力死战,夺路而走,回到大寨,来见关公曰:“今徐晃夺了偃城等处;又兼曹操自引大军,分三路来救樊城;多有人言荆州已被吕蒙袭了。”关公喝曰:“此敌人讹言,以乱我军心耳!东吴吕蒙病危,孺子陆逊代之,不足为虑!”

    言未毕,忽报徐晃兵至。公令备马。平谏曰:“父体未痊,不可与敌。”公曰:“徐晃与吾有旧,深知其能;若彼不退,吾先斩之,以警魏将。”遂披挂提刀上马,奋然而出。魏军见之,无不惊惧。公勒马问曰:“徐公明安在?”魏营门旗开处,徐晃出马,欠身而言曰:“自别君侯,倏忽数载,不想君侯须发已苍白矣!忆昔壮年相从,多蒙教诲,感谢不忘。今君侯英风震于华夏,使故人闻之,不胜叹羡!兹幸得一见,深慰渴怀。”公曰:“吾与公明交契深厚,非比他人;今何故数穷吾儿耶?”晃回顾众将,厉声大叫曰:“若取得云长首级者,重赏千金!”公惊曰:“公明何出此言?”晃曰:“今日乃国家之事,某不敢以私废公。”言讫,挥大斧直取关公。公大怒,亦挥刀迎之。战八十余合,公虽武艺绝伦,终是右臂少力。关平恐公有失,火急鸣金,公拨马回寨。忽闻四下里喊声大震。原来是樊城曹仁闻曹操救兵至,引军杀出城来,与徐晃会合,两下夹攻,荆州兵大乱。关公上马,引众将急奔襄江上流头。背后魏兵追至。关公急渡过襄江,望襄阳而奔。忽流星马到,报说:“荆州已被吕蒙所夺,家眷被陷。”关公大惊。不敢奔襄阳,提兵投公安来。探马又报:“公安傅士仁已降东吴了。”关公大怒。忽催粮人到,报说:“公安傅士仁往南郡,杀了使命,招糜芳都降东吴去了。”

    关公闻言,怒气冲塞,疮口迸裂,昏绝于地。众将救醒,公顾谓司马王甫曰:“悔不听足下之言,今日果有此事!”因问:“沿江上下,何不举火?”探马答曰:“吕蒙使水手尽穿白衣,扮作客商渡江,将精兵伏于【舟冓】【舟鹿】之中,先擒了守台士卒,因此不得举火。”公跌足叹曰:“吾中奸贼之谋矣!有何面目见兄长耶!”管粮都督赵累曰:“今事急矣,可一面差人往成都求救,一面从旱路去取荆州。”关公依言,差马良、伊籍赍文三道,星夜赴成都求救;一面引兵来取荆州,自领前队先行,留廖化、关平断后。却说樊城围解,曹仁引众将来见曹操,泣拜请罪。操曰:“此乃天数,非汝等之罪也。”操重赏三军,亲至四冢寨周围阅视,顾谓众将曰:“荆州兵围堑鹿角数重,徐公明深入其中,竟获全功。孤用兵三十余年,未敢长驱径入敌围。公明真胆识兼优者也!”众皆叹服。操班师还于摩陂驻扎。徐晃兵至,操亲出寨迎之,见晃军皆按队伍而行,并无差乱。操大喜曰:“徐将军真有周亚夫之风矣!”遂封徐晃为平南将军,同夏侯尚守襄阳,以遏关公之师。操因荆州未定,就屯兵于摩陂,以候消息。却说关公在荆州路上,进退无路,谓赵累曰:“目今前有吴兵,后有魏兵,吾在其中,救兵不至,如之奈何?”累曰:“昔吕蒙在陆口时,尝致书君侯,两家约好,共诛操贼,今却助操而袭我,是背盟也。君侯暂驻军于此,可差人遗书吕蒙责之,看彼如何对答。”关公从其言,遂修书遣使赴荆州来。

【片段 9】
恪令安排车仗。方欲出府,有黄犬衔住衣服,嘤嘤作声,如哭之状。恪怒曰:“犬戏我也!”叱左右逐去之,遂乘车出府。行不数步,见车前一道白虹,自地而起,如白练冲天而去。恪甚惊怪,心腹将张约进车前密告曰;“今日宫中设宴,未知好歹,主公不可轻入。”恪听罢,便令回车。行不到十余步,孙峻、滕胤乘马至车前曰:“太傅何故便回?”恪曰:“吾忽然腹痛,不可见天子。”胤曰:“朝廷为太傅军回,不曾面叙,故特设宴相召,兼议大事。太傅虽感贵恙,还当勉强一行。”恪从其言,遂同孙峻、滕胤入宫,张约亦随入。

    恪见吴主孙亮,施礼毕,就席而坐。亮命进酒,恪心疑,辞曰:“病躯不胜杯酌。”孙峻曰:“太傅府中常服药酒,可取饮乎?”恪曰:“可也。”遂令从人回府取自制药酒到,恪方才放心饮之。酒至数巡,吴主孙亮托事先起。孙峻下殿,脱了长服,着短衣,内披环甲,手提利刃,上殿大呼曰:“天子有诏诛逆贼!”诸葛恪大惊,掷杯于地,欲拔剑迎之,头已落地。张约见峻斩恪,挥刀来迎。峻急闪过,刀尖伤其左指。峻转身一刀,砍中张约右臂。武士一齐拥出,砍倒张约,剁为肉泥。孙峻一面令武士收恪家眷,一面令人将张约并诸葛恪尸首,用芦席包裹,以小车载出,弃于城南门外石子岗乱冢坑内。却说诸葛恪之妻正在房中心神恍惚,动止不宁,忽一婢女入房。恪妻问曰:“汝遍身如何血臭?”其婢忽然反目切齿,飞身跳跃,头撞屋梁,口中大叫:“吾乃诸葛恪也!被奸贼孙峻谋杀!”恪合家老幼,惊惶号哭。不一时,军马至,围住府第,将恪全家老幼,俱缚至市曹斩首。时吴建兴二年冬十月也。昔诸葛瑾存日,见恪聪明尽显于外,叹曰:“此子非保家之主也!”又魏光禄大夫张缉,曾对司马师曰:“诸葛恪不久死矣。”师问其故,缉曰:“威震其主,何能久乎?”至此果中其言。却说孙峻杀了诸葛恪,吴主孙亮封峻为丞相、大将军、富春侯,总督中外诸军事。自此权柄尽归孙峻矣。

    且说姜维在成都,接得诸葛恪书,欲求相助伐魏,遂入朝,奏准后主,复起大兵,北伐中原。正是:一度兴师未奏绩,两番讨贼欲成功。未知胜负如何,且看下文分解。



正文 第一百九回 困司马汉将奇谋 废曹芳魏家果报

    蜀汉延熙十六年秋,将军姜维起兵二十万,令廖化、张翼为左右先锋,夏侯霸为参谋,张嶷为运粮使,大兵出阳平关伐魏。维与夏侯霸商议曰:“向取雍州,不克而还;今若再出,必又有准备。公有何高见?”霸曰:“陇上诸郡,只有南安钱粮最广;若先取之,足可为本。向者不克而还,盖因羌兵不至。今可先遣人会羌人于陇右,然后进兵出石营,从董亭直取南安。”维大喜曰:“公言甚妙!”遂遣郤正为使,赍金珠蜀锦入羌,结好羌王。羌王迷当,得了礼物,便起兵五万,令羌将俄何烧戈为大先锋,引兵南安来。

    魏左将军郭淮闻报,飞奏洛阳。司马师问诸将曰:“谁敢去敌蜀兵?”辅国将军徐质曰:“某愿往。”师素知徐质英勇过人,心中大喜,即令徐质为先锋,令司马昭为大都督,领兵望陇西进发。军至董亭,正遇姜维,两军列成阵势。徐质使开出大斧,出马挑战。蜀阵中廖化出迎。战不数合,化拖刀败回。张翼纵马挺枪而迎,战不数合,又败入阵。徐质驱兵掩杀,蜀兵大败,退三十余里。司马昭亦收兵回,各自下寨。

    姜维与夏侯霸商议曰:“徐质勇甚,当以何策擒之?”霸曰:“来日诈败,以埋伏之计胜之。”维曰:“司马昭乃仲达之子,岂不知兵法?若见地势掩映,必不肯追。吾见魏兵累次断吾粮道,今却用此计诱之,可斩徐质矣。”遂唤廖化分付如此如此,又唤张翼分付如此如此:二人领兵去了。一面令军士于路撒下铁蒺藜,寨外多排鹿角,示以久计。

    徐质连日引兵搦战,蜀兵不出。哨马报司马昭说:“蜀兵在铁笼山后,用木牛流马搬运粮草,以为久计,只待羌兵策应。”昭唤徐质曰:“昔日所以胜蜀者,因断彼粮道也。今蜀兵在铁笼山后运粮,汝今夜引兵五千,断其粮道,蜀兵自退矣。”徐质领令,初更时分,引兵望铁笼山来,果见蜀兵二百余人,驱百余头木牛流马,装载粮草而行。魏兵一声喊起,徐质当先拦住。蜀兵尽弃粮草而走。质分兵一半,押送粮草回寨;自引兵一半追来。追不到十里,前面车仗横截去路。质令军士下马拆开车仗,只见两边忽然火起。质急勒马回走,后面山僻窄狭处,亦有车仗截路,火光迸起。质等冒烟突火,纵马而出。一声炮响,两路军杀来:左有廖化,右有张翼,大杀一阵,魏兵大败。

【片段 10】
却说诸葛瞻见救兵不至,谓众将曰:“久守非良图。”遂留子尚与尚书张遵守城,瞻自披挂上马,引三军大开三门杀出。邓艾见兵出,便撤兵退。瞻奋力追杀,忽然一声炮响,四面兵合,把瞻困在垓心。瞻引兵左冲右突,杀死数百人。艾令众军放箭射之,蜀兵四散。瞻中箭落马,乃大呼曰:“吾力竭矣,当以一死报国!”遂拔剑自刎而死。其子诸葛尚在城上,见父死于军中,勃然大怒,遂披挂上马。张遵谏曰:“小将军勿得轻出。”尚叹曰:“吾父子祖孙,荷国厚恩,今父既死于敌,我何用生为!”遂策马杀出,死于阵中。后人有诗赞瞻、尚父子曰:“不是忠臣独少谋,苍天有意绝炎刘。当年诸葛留嘉胤,节义真堪继武侯。”邓艾怜其忠,将父子合葬。乘虚攻打绵竹。张遵、黄崇、李球三人,各引一军杀出。蜀兵寡,魏兵众,三人亦皆战死。艾因此得了绵竹。劳军已毕,遂来取成都。正是:试观后主临危日,无异刘璋受逼时。未知成都如何守御,且看下文分解。



正文 第一百十八回 哭祖庙一王死孝 入西川二士争功

    却说后主在成都,闻邓艾取了绵竹,诸葛瞻父子已亡,大惊,急召文武商议。近臣奏曰:“城外百姓,扶老携幼,哭声大震,各逃生命。”后主惊惶无措。忽哨马报到,说魏兵将近城下。多官议曰:“兵微将寡,难以迎敌;不如早弃成都,奔南中七郡。其地险峻,可以自守,就借蛮兵,再来克复未迟。”光禄大夫谯周曰:“不可。南蛮久反之人,平昔无惠;今若投之,必遭大祸。”多官又奏曰:“蜀、吴既同盟,今事急矣,可以投之。”周又谏曰:“自古以来,无寄他国为天子者。臣料魏能吞吴,吴不能吞魏。若称臣于吴,是一辱也;若吴被魏所吞,陛下再称臣于魏,是两番之辱矣。不如不投吴而降魏。魏必裂土以封陛下,则上能自守宗庙,下可以保安黎民。愿陛下思之。”后主未决,退入宫中。次日,众议纷然。谯周见事急,复上疏诤之。后主从谯周之言,正欲出降;忽屏风后转出一人,厉声而骂周曰:“偷生腐儒,岂可妄议社稷大事!自古安有降天子哉!”后主视之,乃第五子北地王刘谌也。后主生七子:长子刘璿,次子刘瑶,三子刘琮,四子刘瓒,五子即北地王刘谌,六子刘恂,七子刘璩。七子中惟谌自幼聪明,英敏过人,余皆儒善。后主谓谌曰:“今大臣皆议当降,汝独仗血气之勇,欲令满城流血耶?”谌曰:“昔先帝在日,谯周未尝于预国政;今妄议大事,辄起乱言,甚非理也。臣切料成都之兵,尚有数万;姜维全师,皆在剑阁,若知魏兵犯阙,必来救应:内外攻击,可获大功。岂可听腐儒之言,轻废先帝之基业乎?”后主叱之曰:“汝小儿岂识天时!”谌叩头哭曰:“若势穷力极,祸败将及,便当父子君臣背城一战,同死社稷,以见先帝可也。奈何降乎!”后主不听。谌放声大哭曰:“先帝非容易创立基业,今一旦弃之,吾宁死不辱也!”后主令近臣推出宫门,遂令谯周作降书,遣私署侍中张绍、驸马都尉邓良同谯周赍玉玺来雒城请降。时邓艾每日令数百铁骑来成都哨探。当日见立了降旗,艾大喜。不一时,张绍等至,艾令人迎入。三人拜伏于阶下,呈上降款玉玺。艾拆降书视之,大喜,受下玉玺,重待张绍、谯周、邓良等。艾作回书,付三人赍回成都,以安人心。三人拜辞邓艾,径还成都,入见后主,呈上回书,细言邓艾相待之善。后主拆封视之,大喜,即遣太仆蒋显赍敕令姜维早降;遣尚书郎李虎,送文簿与艾:共户二十八万,男女九十四万,带甲将士十万二千,官吏四万,仓粮四十余万,金银各二千斤,锦绮彩绢各二十万匹。余物在库,不及具数。择十二月初一日,君臣出降。北地王刘谌闻知,怒气冲天,乃带剑入宫。其妻崔夫人问曰:“大王今日颜色异常,何也?”谌曰:“魏兵将近,父皇已纳降款,明日君巨出降,社稷从此殄灭。吾欲先死以见先帝于地下,不屈膝于他人也!”崔夫人曰:“贤哉!贤哉!得其死矣!妾请先死,王死未迟。”谌曰:“汝何死耶?”崔夫人曰:“王死父,妾死夫:其义同也。夫亡妻死,何必问焉!”言讫,触柱而死。谌乃自杀其三子,并割妻头,提至昭烈庙中,伏地哭曰:“臣羞见基业弃于他人,故先杀妻子,以绝挂念,后将一命报祖!祖如有灵,知孙之心!”大哭一场,眼中流血,自刎而死。蜀人闻知,无不哀痛。后人有诗赞曰:“君臣甘屈膝,一子独悲伤。去矣西川事,雄哉北地王!捐身酬烈祖,搔首泣穹苍。凛凛人如在,谁云汉已亡?”后主听知北地王自刎,乃令人葬之。次日,魏兵大至。后主率太子诸王,及群臣六十余人,面缚舆榇,出北门十里而降。邓艾扶起后主,亲解其缚,焚其舆榇,并车入城。后人有诗叹曰:“魏兵数万入川来,后主偷生失自裁。黄皓终存欺国意,姜维空负济时才。全忠义士心何烈,守节王孙志可哀。昭烈经营良不易,一朝功业顿成灰。”

三、详细说明

3.1 初始化模型(Ollama 本地模型)

# ===================== 1. 初始化模型(Ollama 本地模型)=====================
# 嵌入模型:embeddinggemma(用于生成文本向量)
embeddings = OllamaEmbeddings(
    model="embeddinggemma",  # 必须与本地拉取的模型名一致
    base_url="http://localhost:11434"  # Ollama 默认端口(无需修改,除非自定义)
)

# 大语言模型:用于生成最终回答(示例用 deepseek-r1:1.5b 等)
llm = OllamaLLM(
    model="deepseek-r1:1.5b",  # 确保已通过 `ollama run deepseek-r1:1.5b` 下载并启动
    temperature=0.1,  # 温度越低,回答越精准(0.1~0.3 适合事实性问答)
    base_url="http://localhost:11434"
)

3.2 加载并处理文档(核心:分割为小片段)

# ===================== 2. 加载并处理文档(核心:分割为小片段)=====================
# 1. 加载本地 TXT 文档(替换为你的文档路径,支持多个文档)
loader = TextLoader("./docs/《三国演义》.txt")  # 示例:本地文档(如技术手册、知识库等)
documents = loader.load()

# 2. 分割文档:将长文档拆分为短片段(避免嵌入时丢失语义,提升检索精度)
text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=2000,  # 每个片段最大字符数(根据文档复杂度调整)
    chunk_overlap=200,  # 片段重叠字符数(保持上下文连贯性)
    length_function=len  # 按字符长度计算
)
split_documents = text_splitter.split_documents(documents)

3.3 构建/加载 Chroma 向量库(核心替换)

# ===================== 3. 构建/加载 Chroma 向量库(核心替换)=====================
# Chroma 配置:本地存储路径、集合名称(可自定义)
CHROMA_DB_PATH = "./chroma_db"  # 向量库本地存储文件夹
COLLECTION_NAME = "knowledge_base"  # 集合名称(类似数据库的表)

# 方式1:新建 Chroma 向量库(首次运行,处理文档并写入)
vector_db = Chroma.from_documents(
    documents=split_documents,
    embedding=embeddings,
    persist_directory=CHROMA_DB_PATH,  # 本地持久化路径
    collection_name=COLLECTION_NAME,  # 集合名称(便于多知识库隔离)
    collection_metadata={"hnsw:space": "cosine"}  # 相似度计算方式(余弦相似度,适合嵌入向量)
)


# # 方式2:加载已保存的 Chroma 向量库(后续运行,跳过文档处理)
# vector_db = Chroma(
#     collection_name=COLLECTION_NAME,
#     embedding_function=embeddings,
#     persist_directory=CHROMA_DB_PATH
# )

3.4 (可选)动态添加新文档到 Chroma(增量更新)

# ===================== (可选)4. 动态添加新文档到 Chroma(增量更新)=====================
# 场景:后续新增文档,无需重建向量库,直接添加
def add_new_documents(new_doc_paths):
    """
    动态添加新文档到 Chroma 向量库
    new_doc_paths: 新文档路径列表(如 ["new_doc1.txt", "new_doc2.pdf"])
    """
    for path in new_doc_paths:
        # 加载新文档(根据后缀选择对应的 Loader)
        if path.endswith(".txt"):
            new_loader = TextLoader(path)
        elif path.endswith(".pdf"):
            from langchain_community.document_loaders import PyPDFLoader
            new_loader = PyPDFLoader(path)
        else:
            print(f"不支持的文档格式:{path}")
            continue

        new_docs = new_loader.load()
        new_split_docs = text_splitter.split_documents(new_docs)

        # 添加到 Chroma 向量库(自动增量更新,无需重建)
        vector_db.add_documents(documents=new_split_docs)
        print(f"已添加文档:{path}")


# 示例:添加新文档(实际使用时取消注释)
# add_new_documents(["new_document.txt", "tech_manual.pdf"])

3.5 构建 RAG 检索链

# ===================== 5. 构建 RAG 检索链(与之前一致)=====================
# 检索器:从 Chroma 中检索最相关的 3 个文档片段
retriever = vector_db.as_retriever(
    search_kwargs={"k": 10}  # k=3 表示取 top3 相关片段
)

# 提示词模板:基于检索到的上下文回答,不编造信息
prompt = ChatPromptTemplate.from_template("""
你是专业的问答助手,必须严格基于以下上下文信息回答用户问题。
如果上下文没有相关内容,直接回复"根据知识库,未找到相关答案",禁止编造信息。

上下文信息:
{context}

用户问题:
{question}
""")

# 构建 RAG 链:检索 → 格式化上下文 → 生成回答
rag_chain = (
        {
            # 检索并拼接上下文(将多个文档片段合并为字符串)
            "context": retriever | (lambda docs: "\n\n".join([d.page_content for d in docs])),
            "question": RunnablePassthrough()  # 透传用户问题
        }
        | prompt  # 注入提示词和上下文
        | llm  # 本地 LLM 生成回答
        | StrOutputParser()  # 解析输出为字符串
)

3.6 测试 RAG 效果

# ===================== 6. 测试 RAG 效果 =====================
if __name__ == "__main__":
    # 测试问题(基于 《三国演义》.txt 中的内容)
    user_question = "诸葛亮是谁,简单介绍下他的功绩"

    # 执行 RAG 链
    result = rag_chain.invoke(user_question)

    # 输出结果
    print("=== RAG 回答 ===")
    print(result)

    # (可选)查看检索到的相关文档片段(调试用)
    retrieved_docs = retriever.invoke(user_question)
    print("\n=== 检索到的相关文档 ===")
    for i, doc in enumerate(retrieved_docs, 1):
        print(f"\n【片段 {i}】")
        print(doc.page_content)

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐