当前位置:首页>python>Python+LangChain/LangGraph框架开发Ai智能体系列��22节 | BM25 + Chroma 混合检索

Python+LangChain/LangGraph框架开发Ai智能体系列��22节 | BM25 + Chroma 混合检索

  • 2026-07-01 03:57:17
Python+LangChain/LangGraph框架开发Ai智能体系列��22节 | BM25 + Chroma 混合检索

一、学习目标

  1. 理解混合检索的价值
    :单一检索方式的局限性,为何需要 BM25 + 向量检索结合
  2. 掌握 BM25 算法原理
    :基于词频-逆文档频率的经典排序算法,擅长精确匹配
  3. 学会 RRF 排名融合
    :Reciprocal Rank Fusion 多路召回结果融合技术
  4. 实战 LangChain 封装
    :将 BM25 封装为标准 Retriever 接口,与向量检索无缝集成

二、核心概念描述

2.1 检索方式对比

特性
BM25
向量检索
核心原理
词频统计 + 长度归一化
语义嵌入 + 余弦相似度
擅长场景
精确匹配(编号、术语、关键词)
语义理解(同义词、上下文)
典型查询
"BUG-2024-00888"、"JWT Token"
"怎么部署到测试环境"
弱点
无法理解语义变体
对精确编号匹配不敏感

2.2 BM25 算法

score(D, Q) = Σ IDF(q_i) * [f(q_i, D) * (k1 + 1)] / [f(q_i, D) + k1 * (1 - b + b * |D|/avgDL)]其中:- f(q_i, D):词项 q_i 在文档 D 中的词频- |D|:文档长度,avgDL:平均文档长度- k1=1.5:词频饱和参数,b=0.75:长度归一化参数

2.3 RRF 排名融合

RRF_score(d) = Σ 1 / (k + rank_i(d))其中:- rank_i(d):文档 d 在第 i 个检索器中的排名(从0开始)- k=60:平滑参数,防止头部文档得分过于集中

核心思想:多个检索器都认可的文档,融合后排名更高。


三、技术架构实现图

┌─────────────────────────────────────────────────────────────┐│                      混合检索流程                            │├─────────────────────────────────────────────────────────────┤│                                                             ││  ┌─────────────┐    ┌─────────────┐    ┌─────────────┐     ││  │   用户查询   │───▶│  查询预处理  │───▶│  并行检索   │     ││  │  (Query)    │    │ (jieba分词) │    │             │     ││  └─────────────┘    └─────────────┘    └──────┬──────┘     ││                                               │             ││                          ┌────────────────────┼────────┐    ││                          ▼                    ▼        │    ││                   ┌─────────────┐      ┌─────────────┐ │    ││                   │  BM25检索   │      │ 向量检索     │ │    ││                   │ (精确匹配)  │      │ (语义匹配)   │ │    ││                   └──────┬──────┘      └──────┬──────┘ │    ││                          │                    │        │    ││                          ▼                    ▼        │    ││                   ┌─────────────┐      ┌─────────────┐ │    ││                   │ 排名列表    │      │ 排名列表     │ │    ││                   │[(id, rank)]│      │[(id, rank)] │ │    ││                   └──────┬──────┘      └──────┬──────┘ │    ││                          └────────────────────┘        │    ││                                           │            │    ││                                           ▼            │    ││                                   ┌─────────────┐      │    ││                                   │  RRF融合    │◀─────┘    ││                                   │  得分计算   │           ││                                   └──────┬──────┘           ││                                          │                  ││                                          ▼                  ││                                   ┌─────────────┐           ││                                   │  结果排序   │           ││                                   │ Top-K 输出 │           ││                                   └─────────────┘           ││                                                             │└─────────────────────────────────────────────────────────────┘

架构说明

层级
组件
职责
输入层
查询预处理
jieba 中文分词,保留特殊编号
检索层
BM25 + Vector
双路并行召回,互补优势
融合层
RRF
多路排名融合,提升整体效果
输出层
结果排序
按融合得分返回 Top-K

四、代码实现

4.1 核心类:BM25Retriever

关键点

  • 继承 BaseRetriever 实现 LangChain 标准接口
  • k1=1.5, b=0.75
     是 BM25 经典参数
  • 中文分词使用 jieba.cut()

4.2 分词实现

设计意图:保留方括号内的编号(如 BUG-2024-00888)不被 jieba 切散。

4.3 RRF 融合算法

4.4 混合检索主流程

4.5 使用示例


五、效果对比示例

查询类型
查询内容
BM25 优势
向量优势
混合效果
精确编号
ORD-2024-00123
排名第1
可能靠后
综合第1
语义理解
部署应用到测试环境
可能不匹配
排名第1
综合第1
混合查询
张三绩效怎么样
匹配"张三"
匹配"绩效"
双高得分

六、总结

混合检索的核心价值在于互补

  • BM25
     保证精确匹配场景的准确率
  • 向量检索
     覆盖语义理解的泛化能力
  • RRF 融合
     让两者优势叠加,而非简单取并集
七、代码运行演示

注意事项

  • 前置条件:

  •   - 运行过之前文章代码(chroma_db 目录已存在)

      - ollama pull nomic-embed-text

      - ollama 模型 qwen3:4b 可用

7.1 本节所有源代码(复制运行有问题下方扫码入群交流)

# -*- coding: utf-8 -*-# ============================================================# 一、文档加载(企业知识库测试数据)# ============================================================def load_sample_docs():    """    加载企业知识库测试文档(15条)    包含:精确匹配类(编号/术语)、语义类(概念理解)、混合类    """    docs = [        # 编号精确匹配        "[工单编号 ORD-2024-00123] 客户:张三,状态:已处理,负责部门:技术支持部,解决时间:2小时",        "[工单编号 ORD-2024-00124] 客户:李四,状态:处理中,负责部门:售后部,解决时间:待定",        "[Bug编号 BUG-2024-00888] HTTP 404错误,发生在用户登录页面,影响版本:v2.1.0,已修复",        "[Bug编号 BUG-2024-00899] NullPointerException,发生在订单模块,影响版本:v2.1.1,处理中",        # 术语精确匹配        "系统配置:JWT Token 过期时间为 3600 秒(1小时),刷新 Token 有效期为 7 天",        "系统配置:Redis Session 超时时间为 30 分钟,MySQL 连接池最大连接数为 100",        "API 接口限流规则:普通用户每秒 10 次请求,VIP 用户每秒 100 次请求",        # 语义匹配(概念理解)        "如何部署应用到测试环境?步骤:1. 登录 Jenkins  2. 选择项目  3. 点击构建  4. 验证部署结果",        "安装教程:Python 依赖通过 pip install -r requirements.txt 安装,Node 依赖通过 npm install",        "服务器迁移指南:迁移前需备份数据库、配置文件、日志文件,迁移后验证服务可用性",        # 混合类(编号+语义)        "[升级指南 v2.1.0 to v2.1.1] 本次更新修复了 BUG-2024-00899 的 NullPointerException,建议所有用户升级",        "[公告] 张三(技术支持部)已提交 ORD-2024-00123 的处理报告,请相关人员查阅",        # 绩效/员工信息        "员工绩效评级:2024年Q1,张三绩效评级为 A(优秀),李四绩效评级为 B(良好),王五绩效评级为 C(待改进)",        "绩效考核标准:A级(>=90分)、B级(80-89分)、C级(70-79分)、D级(<70分)",        "[流程文档] 请假申请流程:员工提交 → 部门主管审批 → HR 备案 → 系统记录",    ]    return docs# ============================================================# 二、BM25 检索器(LangChain BaseRetriever 封装)# ============================================================from typing import ListDictTupleOptionalAnyfrom langchain_core.retrievers import BaseRetrieverfrom langchain_core.documents import Documentfrom pydantic import Fieldimport jiebafrom rank_bm25 import BM25Okapidef get_doc_id(doc: str) -> str:    """从文档内容提取 doc_id(工单/Bug编号等)"""    import re    match = re.search(r'\[([^\]]+)\]', doc)    if match:        return match.group(1)    return doc[:30]class BM25Retriever(BaseRetriever):    """    BM25 检索器,封装为 LangChain BaseRetriever    Pydantic v2 继承规范(LangChain BaseRetriever):    - 用 __init__ 参数直接传值给 super().__init__()    - 普通实例变量(_bm25/_tokenized_corpus)用 self.xxx 直接赋值    - __init__ 结束后 model_post_init 会被 Pydantic 自动调用    """    # 类级别:显式声明 Pydantic 字段    docs: List[str] = Field(default_factory=list)    doc_ids: List[str] = Field(default_factory=list)    k: int = Field(default=5)    def __init__(self, docs: List[str], doc_ids: List[str] | None = None,                 k: int = 5, k1: float = 1.5, b: float = 0.75):        # 自动生成 doc_ids        _doc_ids = doc_ids if doc_ids is not None else [get_doc_id(d) for d in docs]        # 分词        _tokenized = [self._tokenize(doc) for doc in docs]        # 构建 BM25 模型        _bm25 = BM25Okapi(_tokenized, k1=k1, b=b)        # 调用父类 __init__(传递 Pydantic 字段)        super().__init__(docs=docs, doc_ids=_doc_ids, k=k)        # 普通实例变量(Pydantic 不会管这些)        self._tokenized_corpus = _tokenized        self._bm25 = _bm25    def model_post_init(self, _context: Any) -> None:        """        Pydantic v2 钩子:在父类 __init__ 完成后调用        用于依赖 self.xxx 的初始化逻辑(BM25 在 __init__ 里已构建,此处为空)        """        pass    @staticmethod    def _tokenize(text: str) -> List[str]:        """中英文混合分词"""        import re        brackets = re.findall(r'\[([^\]]+)\]', text)        brackets_tokens = [b.split() for b in brackets]        tokens = list(jieba.cut(text.lower()))        tokens = [t.strip() for t in tokens if t.strip()]        for bt in brackets_tokens:            tokens.extend(bt)        return tokens    def _get_relevant_documents(self, query: str) -> List[Document]:        """核心:BM25 得分计算,返回 Top-K 文档"""        query_tokens = self._tokenize(query)        scores = self._bm25.get_scores(query_tokens)        ranked = sorted(zip(scores, self.doc_ids, self.docs),                        key=lambda x: x[0], reverse=True)        top_k = ranked[:self.k]        return [            Document(page_content=doc_content,                     metadata={"doc_id": doc_id, "score"float(score)})            for score, doc_id, doc_content in top_k        ]    def get_scores(self, query: str) -> Dict[strfloat]:        """获取所有文档的 BM25 得分(用于 RRF 融合)"""        query_tokens = self._tokenize(query)        scores = self._bm25.get_scores(query_tokens)        return {doc_id: float(score)                for doc_id, score in zip(self.doc_ids, scores)}# ============================================================# 三、向量检索器(Chroma + Ollama Embeddings)# ============================================================import osimport shutildef run_chromadb_patch():    """猴子补丁:修复 chromadb 1.5.7 + langchain-chroma 1.1.0 兼容性"""    if getattr(run_chromadb_patch, '_done'False):        return    run_chromadb_patch._done = True    try:        import chromadb.api        for _name in getattr(chromadb.api, '__all__'dir(chromadb.api)):            if _name.startswith('_'):                continue            try:                _cls = getattr(chromadb.api, _name)                if hasattr(_cls, 'get_or_create_collection'):                    _orig = _cls.get_or_create_collection                    def _patched(self, name, configuration_metadata=None,                                 get_or_create=False, embeddings=None,                                 data_loader=None, **kwargs):                        kwargs.pop('embedding_function'None)                        return _orig(self, name,                                     configuration_metadata=configuration_metadata,                                     get_or_create=get_or_create,                                     embeddings=embeddings,                                     data_loader=data_loader, **kwargs)                    _cls.get_or_create_collection = _patched                    print("[OK] chromadb patch applied")                    break            except Exception:                continue    except Exception:        passclass OllamaEmbeddings:    """    自定义 Ollama Embeddings 实现,绕过 langchain-ollama 的兼容性问题    适配 LangChain 1.x + langchain-chroma 1.x    """    def __init__(self, model: str = "nomic-embed-text:latest",                 base_url: str = "http://localhost:11434"):        self.model = model        self.base_url = base_url        self._client = None    def _get_client(self):        if self._client is None:            try:                import ollama                self._client = ollama.Client(host=self.base_url)            except ImportError:                raise ImportError("请安装 ollama: pip install ollama")        return self._client    def embed_documents(self, texts: List[str]) -> List[List[float]]:        """嵌入多个文档"""        client = self._get_client()        embeddings = []        for text in texts:            response = client.embeddings(model=self.model, prompt=text)            embeddings.append(response["embedding"])        return embeddings    def embed_query(self, text: str) -> List[float]:        """嵌入单个查询"""        client = self._get_client()        response = client.embeddings(model=self.model, prompt=text)        return response["embedding"]def get_vector_retriever(docs: List[str]) -> BaseRetriever:    """    获取向量检索器(Chroma + Ollama Embeddings)    依赖:Ollama 服务运行中 + nomic-embed-text:v1.5 模型已拉取    """    run_chromadb_patch()    from langchain_chroma import Chroma    embeddings = OllamaEmbeddings(model="nomic-embed-text:latest",                                  base_url="http://localhost:11434")    # 兼容交互式环境(__file__ 可能不存在)    try:        _base_dir = os.path.dirname(os.path.abspath(__file__))    except NameError:        _base_dir = os.getcwd()    persist_dir = os.path.join(_base_dir, "chroma_db")    if os.path.exists(persist_dir):        shutil.rmtree(persist_dir)    vectorstore = Chroma.from_texts(        texts=docs,        embedding=embeddings,        persist_directory=persist_dir,        ids=[get_doc_id(d) for d in docs],    )    return vectorstore.as_retriever(search_kwargs={"k"5})# ============================================================# 四、RRF 排名融合# ============================================================def rrf_fusion(ranker_results: List[Tuple[strList[Tuple[strint]]]],               k: int = 60) -> List[Tuple[strfloat]]:    """    Reciprocal Rank Fusion(倒数排名融合)    原理:每个检索器给文档打排名(第1名、第2名...),    RRF 得分 = sum(1/(k + rank_i)),    多个检索器都认可的文档得分更高。    """    from collections import defaultdict    doc_scores: Dict[strfloat] = defaultdict(float)    for _ranker_name, ranked_list in ranker_results:        for doc_id, rank in ranked_list:            doc_scores[doc_id] += 1.0 / (k + rank)    return sorted(doc_scores.items(), key=lambda x: x[1], reverse=True)# ============================================================# 五、混合检索主函数# ============================================================def hybrid_search(query: str,                  bm25_retriever: BM25Retriever,                  vector_retriever: BaseRetriever,                  top_k: int = 5,                  rrf_k: int = 60) -> List[Tuple[Document, floatDict[strAny]]]:    """    混合检索:BM25 + 向量 -> RRF 融合    """    # Step1: 分别检索    bm25_scores = bm25_retriever.get_scores(query)    vector_results = vector_retriever.invoke(query)    # Step2: 构建排名列表    bm25_ranked = sorted(bm25_scores.items(), key=lambda x: x[1], reverse=True)    bm25_ranked_list = [(doc_id, rank)                         for rank, (doc_id, _) in enumerate(bm25_ranked)]    doc_id_to_doc = {d.metadata.get("doc_id"""): d for d in vector_results}    vector_ranked_list = [(d.metadata.get("doc_id"f"v{ri}"), ri)                          for ri, d in enumerate(vector_results)]    # Step3: RRF 融合    fused = rrf_fusion([("bm25", bm25_ranked_list), ("vector", vector_ranked_list)],                       k=rrf_k)    # Step4: 组装最终结果    results = []    for doc_id, rrf_score in fused[:top_k]:        bm25_doc = next((d for d in bm25_retriever.docs                         if get_doc_id(d) == doc_id), None)        vector_doc = doc_id_to_doc.get(doc_id)        if bm25_doc is None and vector_doc:            bm25_doc = vector_doc.page_content        if bm25_doc is None:            continue        bm25_rank = next((r for d_id, r in bm25_ranked_list if d_id == doc_id), None)        vector_rank = next((r for d_id, r in vector_ranked_list if d_id == doc_id), None)        results.append((            Document(page_content=bm25_doc,                     metadata={"doc_id": doc_id, "rrf_score": rrf_score}),            rrf_score,            {"bm25_rank": bm25_rank, "vector_rank": vector_rank,             "bm25_score": bm25_scores.get(doc_id, 0),             "vector_score": (vector_doc.metadata.get("score"0)                              if vector_doc else 0)}        ))    return results# ============================================================# 六、演示# ============================================================def demo():    """演示:三种检索方式对比"""    docs = load_sample_docs()    print(f"[OK] Load {len(docs)} docs")    # BM25    bm25_retriever = BM25Retriever(docs=docs, k=5)    print(f"[OK] BM25 retriever ready (_bm25={type(bm25_retriever._bm25).__name__})")    # 向量(可选)    try:        vector_retriever = get_vector_retriever(docs)        print("[OK] Vector retriever ready (Chroma+Ollama)")        has_vector = True    except Exception as e:        print(f"[WARN] Vector retriever unavailable ({e}), skip vector part")        vector_retriever = None        has_vector = False    test_queries = [        ("ORD-2024-00123""exact-id"),        ("张三的工单""exact-name"),        ("部署应用到测试环境怎么做""semantic"),        ("请假申请流程""semantic"),        ("JWT 配置多少秒""exact-term"),    ]    for query, qtype in test_queries:        print(f"\n--- Query ({qtype}): {query} ---")        bm25_results = bm25_retriever.invoke(query)        print(f"[BM25 Top-3]")        for i, doc in enumerate(bm25_results[:3], 1):            print(f"  #{i} score={doc.metadata['score']:.4f}{doc.metadata['doc_id']}")        if has_vector and vector_retriever:            vector_results = vector_retriever.invoke(query)            print(f"[Vector Top-3]")            for i, doc in enumerate(vector_results[:3], 1):                print(f"  #{i}{doc.page_content[:60]}")            hybrid = hybrid_search(query, bm25_retriever, vector_retriever, top_k=3)            print(f"[Hybrid Top-3]")            for i, (doc, score, ranks) in enumerate(hybrid[:3], 1):                print(f"  #{i} rrf={score:.4f}  b_rank={ranks['bm25_rank']}  v_rank={ranks['vector_rank']}")# ============================================================# 七、快捷函数(供外部导入)# ============================================================_bm25_r: Optional[BM25Retriever] = None_vec_r: Optional[BaseRetriever] = Nonedef get_retrievers():    global _bm25_r, _vec_r    if _bm25_r is None:        docs = load_sample_docs()        _bm25_r = BM25Retriever(docs=docs, k=5)        try:            _vec_r = get_vector_retriever(docs)        except Exception as e:            print(f"[WARN] Vector retriever unavailable: {e}")            _vec_r = None    return _bm25_r, _vec_rdef search(query: str, mode: str = "hybrid", top_k: int = 5) -> List[Document]:    """快捷搜索函数"""    bm25_r, vec_r = get_retrievers()    if mode == "bm25":        return bm25_r.invoke(query)    if mode == "vector":        return (vec_r.invoke(query) if vec_r else bm25_r.invoke(query))    # hybrid    if vec_r is None:        return bm25_r.invoke(query)    results, _, _ = zip(*hybrid_search(query, bm25_r, vec_r, top_k=top_k))    return list(results)if __name__ == "__main__":    demo()
7.2运行结果

最新文章

随机文章

基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-07-04 12:27:33 HTTP/2.0 GET : https://f.mffb.com.cn/a/488199.html
  2. 运行时间 : 0.111097s [ 吞吐率:9.00req/s ] 内存消耗:4,636.20kb 文件加载:140
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=6d528ed641211a474fa22c0b13ff9889
  1. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/public/index.php ( 0.79 KB )
  2. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/autoload.php ( 0.17 KB )
  3. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_real.php ( 2.49 KB )
  4. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/platform_check.php ( 0.90 KB )
  5. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/ClassLoader.php ( 14.03 KB )
  6. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_static.php ( 4.90 KB )
  7. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper.php ( 8.34 KB )
  8. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/helper.php ( 2.19 KB )
  9. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/helper.php ( 1.47 KB )
  10. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/stubs/load_stubs.php ( 0.16 KB )
  11. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Exception.php ( 1.69 KB )
  12. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Facade.php ( 2.71 KB )
  13. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/deprecation-contracts/function.php ( 0.99 KB )
  14. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap.php ( 8.26 KB )
  15. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap80.php ( 9.78 KB )
  16. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/Resources/functions/dump.php ( 1.49 KB )
  17. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-dumper/src/helper.php ( 0.18 KB )
  18. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/VarDumper.php ( 4.30 KB )
  19. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/App.php ( 15.30 KB )
  20. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Container.php ( 15.76 KB )
  21. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/container/src/ContainerInterface.php ( 1.02 KB )
  22. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/provider.php ( 0.19 KB )
  23. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Http.php ( 6.04 KB )
  24. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Str.php ( 7.29 KB )
  25. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Env.php ( 4.68 KB )
  26. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/common.php ( 0.03 KB )
  27. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/helper.php ( 18.78 KB )
  28. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Config.php ( 5.54 KB )
  29. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/app.php ( 0.95 KB )
  30. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cache.php ( 0.78 KB )
  31. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/console.php ( 0.23 KB )
  32. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cookie.php ( 0.56 KB )
  33. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/database.php ( 2.48 KB )
  34. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Env.php ( 1.67 KB )
  35. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/filesystem.php ( 0.61 KB )
  36. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/lang.php ( 0.91 KB )
  37. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/log.php ( 1.35 KB )
  38. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/middleware.php ( 0.19 KB )
  39. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/route.php ( 1.89 KB )
  40. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/session.php ( 0.57 KB )
  41. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/trace.php ( 0.34 KB )
  42. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/view.php ( 0.82 KB )
  43. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/event.php ( 0.25 KB )
  44. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Event.php ( 7.67 KB )
  45. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/service.php ( 0.13 KB )
  46. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/AppService.php ( 0.26 KB )
  47. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Service.php ( 1.64 KB )
  48. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Lang.php ( 7.35 KB )
  49. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/lang/zh-cn.php ( 13.70 KB )
  50. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/Error.php ( 3.31 KB )
  51. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/RegisterService.php ( 1.33 KB )
  52. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/services.php ( 0.14 KB )
  53. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/PaginatorService.php ( 1.52 KB )
  54. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ValidateService.php ( 0.99 KB )
  55. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ModelService.php ( 2.04 KB )
  56. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Service.php ( 0.77 KB )
  57. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Middleware.php ( 6.72 KB )
  58. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/BootService.php ( 0.77 KB )
  59. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Paginator.php ( 11.86 KB )
  60. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/Validate.php ( 63.20 KB )
  61. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Model.php ( 23.55 KB )
  62. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Attribute.php ( 21.05 KB )
  63. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/AutoWriteData.php ( 4.21 KB )
  64. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Conversion.php ( 6.44 KB )
  65. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/DbConnect.php ( 5.16 KB )
  66. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/ModelEvent.php ( 2.33 KB )
  67. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/RelationShip.php ( 28.29 KB )
  68. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Arrayable.php ( 0.09 KB )
  69. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Jsonable.php ( 0.13 KB )
  70. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/contract/Modelable.php ( 0.09 KB )
  71. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Db.php ( 2.88 KB )
  72. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/DbManager.php ( 8.52 KB )
  73. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Log.php ( 6.28 KB )
  74. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Manager.php ( 3.92 KB )
  75. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerTrait.php ( 2.69 KB )
  76. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerInterface.php ( 2.71 KB )
  77. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cache.php ( 4.92 KB )
  78. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/simple-cache/src/CacheInterface.php ( 4.71 KB )
  79. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Arr.php ( 16.63 KB )
  80. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/driver/File.php ( 7.84 KB )
  81. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/Driver.php ( 9.03 KB )
  82. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/CacheHandlerInterface.php ( 1.99 KB )
  83. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/Request.php ( 0.09 KB )
  84. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Request.php ( 55.78 KB )
  85. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/middleware.php ( 0.25 KB )
  86. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Pipeline.php ( 2.61 KB )
  87. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/TraceDebug.php ( 3.40 KB )
  88. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/middleware/SessionInit.php ( 1.94 KB )
  89. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Session.php ( 1.80 KB )
  90. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/driver/File.php ( 6.27 KB )
  91. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/SessionHandlerInterface.php ( 0.87 KB )
  92. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/Store.php ( 7.12 KB )
  93. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Route.php ( 23.73 KB )
  94. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleName.php ( 5.75 KB )
  95. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Domain.php ( 2.53 KB )
  96. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleGroup.php ( 22.43 KB )
  97. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Rule.php ( 26.95 KB )
  98. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleItem.php ( 9.78 KB )
  99. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/route/app.php ( 1.72 KB )
  100. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Route.php ( 4.70 KB )
  101. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/dispatch/Controller.php ( 4.74 KB )
  102. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Dispatch.php ( 10.44 KB )
  103. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/controller/Index.php ( 4.81 KB )
  104. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/BaseController.php ( 2.05 KB )
  105. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/facade/Db.php ( 0.93 KB )
  106. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/connector/Mysql.php ( 5.44 KB )
  107. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/PDOConnection.php ( 52.47 KB )
  108. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Connection.php ( 8.39 KB )
  109. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/ConnectionInterface.php ( 4.57 KB )
  110. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/builder/Mysql.php ( 16.58 KB )
  111. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Builder.php ( 24.06 KB )
  112. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseBuilder.php ( 27.50 KB )
  113. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Query.php ( 15.71 KB )
  114. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseQuery.php ( 45.13 KB )
  115. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TimeFieldQuery.php ( 7.43 KB )
  116. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/AggregateQuery.php ( 3.26 KB )
  117. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ModelRelationQuery.php ( 20.07 KB )
  118. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ParamsBind.php ( 3.66 KB )
  119. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ResultOperation.php ( 7.01 KB )
  120. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/WhereQuery.php ( 19.37 KB )
  121. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/JoinAndViewQuery.php ( 7.11 KB )
  122. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TableFieldInfo.php ( 2.63 KB )
  123. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/Transaction.php ( 2.77 KB )
  124. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/driver/File.php ( 5.96 KB )
  125. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/LogHandlerInterface.php ( 0.86 KB )
  126. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/Channel.php ( 3.89 KB )
  127. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/event/LogRecord.php ( 1.02 KB )
  128. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/Collection.php ( 16.47 KB )
  129. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/View.php ( 1.70 KB )
  130. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/View.php ( 4.39 KB )
  131. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Response.php ( 8.81 KB )
  132. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/response/View.php ( 3.29 KB )
  133. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cookie.php ( 6.06 KB )
  134. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-view/src/Think.php ( 8.38 KB )
  135. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/TemplateHandlerInterface.php ( 1.60 KB )
  136. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/Template.php ( 46.61 KB )
  137. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/driver/File.php ( 2.41 KB )
  138. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/contract/DriverInterface.php ( 0.86 KB )
  139. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/runtime/temp/067d451b9a0c665040f3f1bdd3293d68.php ( 11.98 KB )
  140. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Html.php ( 4.42 KB )
  1. CONNECT:[ UseTime:0.000504s ] mysql:host=127.0.0.1;port=3306;dbname=f_mffb;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.000808s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.001114s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.000293s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.000632s ]
  6. SELECT * FROM `set` [ RunTime:0.000244s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.000712s ]
  8. SELECT * FROM `article` WHERE `id` = 488199 LIMIT 1 [ RunTime:0.001847s ]
  9. UPDATE `article` SET `lasttime` = 1783139253 WHERE `id` = 488199 [ RunTime:0.007773s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 66 LIMIT 1 [ RunTime:0.002721s ]
  11. SELECT * FROM `article` WHERE `id` < 488199 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.000728s ]
  12. SELECT * FROM `article` WHERE `id` > 488199 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.000688s ]
  13. SELECT * FROM `article` WHERE `id` < 488199 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.004910s ]
  14. SELECT * FROM `article` WHERE `id` < 488199 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.007629s ]
  15. SELECT * FROM `article` WHERE `id` < 488199 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.007415s ]
0.113567s