新闻详情

新闻详情

首页 / 资讯中心 / 详情

AI Agent后端实战:Docker Compose编排、ElasticSearch与BM25检索优化

发布时间:2026/9/28 13:10:24来源:尧图网络
AI Agent后端实战:Docker Compose编排、ElasticSearch与BM25检索优化
1. 为什么AI Agent后端绕不开这几个组件做AI Agent应用后端绕不开三件事服务怎么编排、知识怎么检索、相关性怎么算。这三个问题分别对应Docker Compose、ElasticSearch含IK分词和BM25算法。很多人一上来就写Agent的Prompt和工具调用逻辑结果本地跑通了一部署就各种环境问题或者检索出来的内容驴唇不对马嘴Agent拿着错误的知识去回答效果还不如不用RAG。我自己在搭建Agent后端的过程中踩过不少坑。最开始用docker run一条条起容器每次重启环境都要重新敲一遍命令参数还容易记错。后来换成Docker Compose一个docker compose up -d全部搞定。检索这块一开始用简单的关键词匹配中文分词一塌糊涂后来上了ElasticSearch加IK分词器再配合BM25的相关性打分召回质量明显上了一个台阶。这篇内容适合正在做AI Agent后端、RAG系统、知识库检索的开发者。不管你是在Windows上做本地开发还是在Ubuntu服务器上部署下面这些实操细节都能直接参考。我会把Docker Compose的编排写法、ElasticSearch和IK的安装配置、BM25的打分原理和调参经验以及实际排查问题的思路都讲清楚。2. Docker Compose编排从手动docker run到一键启动2.1 为什么Agent后端需要Docker ComposeAI Agent后端通常不是单一服务它至少包含Agent主服务、向量数据库或搜索引擎、缓存Redis、可能还有Nacos做配置中心。如果每个都用docker run手动起你会面临几个问题容器之间的网络要手动创建、启动顺序要手动控制、环境变量要一个个传、端口映射容易冲突。更麻烦的是换一台机器或者重装系统后这些命令你得重新来一遍。Docker Compose解决的就是这个问题。它用一个YAML文件描述所有服务、网络、卷、环境变量一条命令拉起整个技术栈。对于Agent后端来说这意味着你的开发环境、测试环境、生产环境可以用同一份编排文件只需要通过.env文件或--env-file参数切换配置。提示Docker Compose V2已经作为Docker CLI的插件存在命令是docker compose中间有空格而不是老版本的docker-compose中间有横线。如果你敲docker compose提示unknown command说明你的Docker版本太老或者Compose插件没装。2.2 安装Docker Compose的正确姿势在Ubuntu上安装Docker Compose推荐用Docker官方仓库的方式而不是apt install docker-compose。后者装的是老版本Python实现的Compose V1性能和兼容性都不如V2。# 更新包索引并安装必要依赖 sudo apt-get update sudo apt-get install ca-certificates curl gnupg # 添加Docker官方GPG密钥 sudo install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg sudo chmod ar /etc/apt/keyrings/docker.gpg # 添加Docker仓库 echo deb [arch$(dpkg --print-architecture) signed-by/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release echo $VERSION_CODENAME) stable | sudo tee /etc/apt/sources.list.d/docker.list /dev/null # 安装Docker Engine和Compose插件 sudo apt-get update sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin装完之后验证一下docker compose version # 应该输出类似 Docker Compose version v2.24.0 的信息Windows上更简单直接装Docker Desktop它自带Compose插件。装完后在PowerShell里执行docker compose version确认即可。如果你用的是WSL2后端建议把项目文件放在WSL2的文件系统里而不是挂载Windows盘符否则文件IO性能会差很多ElasticSearch这种对磁盘IO敏感的服务尤其明显。2.3 一份可复用的Agent后端Compose编排下面这份docker-compose.yml是我在实际项目中反复打磨过的包含ElasticSearch、Redis和Nacos三个核心服务。你可以根据自己的需求增删。version: 3.8 services: elasticsearch: image: docker.elastic.co/elasticsearch/elasticsearch:8.12.0 container_name: agent-es environment: - discovery.typesingle-node - xpack.security.enabledfalse - ES_JAVA_OPTS-Xms1g -Xmx1g - bootstrap.memory_locktrue ulimits: memlock: soft: -1 hard: -1 volumes: - es_data:/usr/share/elasticsearch/data - ./plugins:/usr/share/elasticsearch/plugins ports: - 9200:9200 - 9300:9300 networks: - agent-net healthcheck: test: [CMD-SHELL, curl -f http://localhost:9200/_cluster/health || exit 1] interval: 10s timeout: 5s retries: 5 redis: image: redis:7.2-alpine container_name: agent-redis command: redis-server --appendonly yes --requirepass ${REDIS_PASSWORD:-agent123} volumes: - redis_data:/data ports: - 6379:6379 networks: - agent-net nacos: image: nacos/nacos-server:v2.3.0 container_name: agent-nacos environment: - MODEstandalone - SPRING_DATASOURCE_PLATFORMmysql - MYSQL_SERVICE_HOSTmysql - MYSQL_SERVICE_PORT3306 - MYSQL_SERVICE_DB_NAMEnacos - MYSQL_SERVICE_USERnacos - MYSQL_SERVICE_PASSWORDnacos ports: - 8848:8848 - 9848:9848 depends_on: - mysql networks: - agent-net mysql: image: mysql:8.0 container_name: agent-mysql environment: - MYSQL_ROOT_PASSWORDroot123 - MYSQL_DATABASEnacos - MYSQL_USERnacos - MYSQL_PASSWORDnacos volumes: - mysql_data:/var/lib/mysql networks: - agent-net volumes: es_data: redis_data: mysql_data: networks: agent-net: driver: bridge这份编排里有几个关键设计点值得说明。discovery.typesingle-node让ES以单节点模式启动省去集群发现的配置麻烦开发环境足够用。ES_JAVA_OPTS限制JVM堆内存为1GB因为ES默认会吃掉大量内存不限制的话你的开发机可能被拖垮。bootstrap.memory_locktrue配合ulimits.memlock防止ES内存被交换到磁盘这对检索性能影响很大。Nacos 3.x的部署方式和2.x有区别如果你用的是3.x版本镜像tag和环境变量需要调整。3.x对JDK版本要求更高且部分配置项名称有变化建议先查一下对应版本的官方Docker部署说明。2.4 启动顺序与依赖管理depends_on只保证容器启动顺序不保证服务就绪。比如Nacos依赖MySQL但MySQL容器启动了不代表数据库已经可以接受连接。这时候healthcheck就派上用场了。上面的编排里给ES加了健康检查你可以用docker compose ps查看健康状态。更稳妥的做法是在应用层做重试。Agent主服务连接ES时如果第一次连接失败不要直接崩溃而是等待几秒后重试。Spring Boot项目里可以用spring.elasticsearch.connection-timeout和重试配置来处理。# 启动所有服务 docker compose up -d # 查看服务状态和健康检查结果 docker compose ps # 查看某个服务的日志 docker compose logs -f elasticsearch # 停止并删除容器保留数据卷 docker compose down # 停止并删除容器和数据卷彻底清理 docker compose down -v注意docker compose down -v会删除数据卷ES里的索引数据、MySQL里的数据都会丢失。开发环境随意生产环境千万别手滑。3. ElasticSearch与IK分词器中文检索的基石3.1 ElasticSearch在Agent后端中的角色AI Agent需要知识库来支撑回答而知识库的核心是检索。ElasticSearch在这里承担的是全文检索和相关性排序的角色。和向量检索相比ES的BM25检索在关键词精确匹配、短语匹配、过滤条件组合方面更成熟而且延迟低、可控性强。实际项目中我通常用ES做第一路召回向量检索做第二路召回然后合并排序。ES 8.x默认开启了安全认证但开发环境为了省事上面编排里用xpack.security.enabledfalse关掉了。生产环境一定要开启并配置好证书和用户密码。3.2 IK分词器的安装与验证IK分词器是ES中文检索的标配插件。没有它ES对中文的处理是按单字切分的人工智能会被切成人、工、智、能四个字检索效果极差。安装IK分词器有两种方式。一种是在编排文件里挂载plugins目录把IK插件解压后放进去。另一种是进入容器手动安装。推荐第一种因为可复现。# 下载IK分词器版本必须和ES版本严格一致 # 假设ES版本是8.12.0 wget https://github.com/infinilabs/analysis-ik/releases/download/v8.12.0/elasticsearch-analysis-ik-8.12.0.zip # 解压到plugins目录下的ik文件夹 mkdir -p ./plugins/ik unzip elasticsearch-analysis-ik-8.12.0.zip -d ./plugins/ik # 重启ES容器使插件生效 docker compose restart elasticsearch验证IK是否安装成功# 查看已安装插件 curl -X GET http://localhost:9200/_cat/plugins?v # 测试IK分词效果 curl -X POST http://localhost:9200/_analyze -H Content-Type: application/json -d { analyzer: ik_max_word, text: 人工智能Agent后端开发 }如果返回的结果里能看到人工智能、Agent、后端、开发等词说明IK工作正常。ik_max_word是细粒度分词适合索引阶段ik_smart是粗粒度分词适合查询阶段。实际使用中索引时用ik_max_word提高召回查询时用ik_smart提高精度这是一个常见的组合策略。3.3 索引Mapping设计的关键决策Mapping决定了字段如何被索引和检索。对于Agent知识库我通常会把字段分为三类全文检索字段、精确过滤字段、元数据字段。{ mappings: { properties: { title: { type: text, analyzer: ik_max_word, search_analyzer: ik_smart }, content: { type: text, analyzer: ik_max_word, search_analyzer: ik_smart }, doc_type: { type: keyword }, source: { type: keyword }, created_at: { type: date, format: yyyy-MM-dd HH:mm:ss||epoch_millis }, tags: { type: keyword } } } }keyword类型不分词适合精确匹配和聚合。text类型分词后建倒排索引适合全文检索。doc_type和source用keyword这样你可以用term查询精确过滤某个来源的文档。tags用keyword数组支持多标签过滤。提示Mapping一旦创建字段类型不能直接修改。如果设计错了只能重建索引再reindex。所以前期花十分钟想清楚字段类型比后期花两小时迁移数据划算得多。3.4 写入性能与磁盘问题的判断ES写入慢是常见问题但原因可能出在多个环节。你需要一套判断方法而不是盲目调参。先看线程池和队列curl -X GET http://localhost:9200/_cat/thread_pool/write?vhnode_name,name,active,queue,rejected如果rejected持续大于0说明写入请求被拒绝线程池满了。这时候要么降低写入速率要么增加write线程池的队列大小。再看磁盘IO# 在宿主机上查看磁盘IO iostat -x 1 5 # 关注 %util 和 await 两个指标 # %util 接近100%说明磁盘饱和 # await 明显升高说明IO延迟大如果%util长期接近100%await超过几十毫秒那基本可以确定是磁盘瓶颈。ES对磁盘IO非常敏感尤其是使用机械硬盘或者网络存储时。换成SSD会有质的提升。还有一个容易忽略的点是段合并segment merge。ES写入时先写translog和内存buffer然后refresh成segment后台再merge小segment。如果merge跟不上写入速度会触发indexing_pressure限制写入。查看方式curl -X GET http://localhost:9200/_nodes/stats/indices/segments?pretty如果segment数量持续增长不下降说明merge压力大。可以适当调大index.merge.scheduler.max_thread_count但根本解决办法还是提升磁盘IO能力。4. BM25打分机制相关性排序的核心逻辑4.1 BM25到底在算什么BM25Best Matching 25是ES默认的相关性打分算法。它的核心思想是一个词在文档中出现次数越多文档越相关但这个词在整个语料库中越罕见权重越高同时要考虑文档长度长文档天然容易包含更多词需要做归一化。公式看起来复杂但拆开理解就三部分TF部分词频越高分数越高但有饱和上限。出现100次和出现10次分数差距不是10倍而是接近饱和。IDF部分词越罕见权重越高。人工智能比的重要得多因为后者几乎每篇文档都有。文档长度归一化长文档的TF会被惩罚避免长文档因为词多而占便宜。ES的BM25有两个可调参数k1和b。k1控制词频饱和速度默认1.2b控制文档长度归一化程度默认0.75。大部分场景下默认值就够用但特定场景可以调。4.2 用explain看打分细节当你发现检索结果排序不符合预期时explain是你的第一排查工具。curl -X POST http://localhost:9200/agent_knowledge/_search -H Content-Type: application/json -d { query: { match: { content: Docker Compose 部署 } }, explain: true }返回结果里会详细列出每个文档的分数是怎么算出来的哪个词贡献了多少分TF是多少IDF是多少长度归一化因子是多少。通过这个你能精确知道为什么某个文档排在前面或后面。我遇到过一个典型问题用户搜ES安装结果一篇讲ES安装和配置的长文档排在了一篇专门讲ES安装步骤的短文档前面。用explain一看长文档因为包含更多匹配词安装出现多次TF分高但内容其实更泛。解决办法是给title字段更高的boost因为标题匹配通常意味着主题更相关。{ query: { multi_match: { query: ES安装, fields: [title^3, content^1], type: best_fields } } }title^3表示标题字段的分数乘以3这样标题匹配的文档会获得更高权重。4.3 BM25与向量检索的配合策略纯BM25检索有它的局限无法处理语义相似但用词不同的情况。比如用户搜容器编排工具一篇讲Docker Compose使用指南的文档可能匹配不上因为字面没有重叠。这时候就需要向量检索来补充。我的做法是双路召回融合排序BM25召回Top 50向量检索召回Top 50用RRFReciprocal Rank Fusion或加权分数融合两路结果取融合后的Top 10送给Agent作为上下文RRF的公式很简单score sum(1 / (k rank))k通常取60。它的好处是不需要归一化两路分数直接基于排名融合鲁棒性强。def rrf_fusion(bm25_results, vector_results, k60): scores {} for rank, doc in enumerate(bm25_results): scores[doc[id]] scores.get(doc[id], 0) 1 / (k rank 1) for rank, doc in enumerate(vector_results): scores[doc[id]] scores.get(doc[id], 0) 1 / (k rank 1) return sorted(scores.items(), keylambda x: x[1], reverseTrue)这段代码可以直接用bm25_results和vector_results分别是两路召回的文档列表每个文档至少包含id字段。4.4 分词质量对BM25的影响BM25的打分建立在分词结果之上。如果分词切错了TF和IDF都是错的打分自然不准。IK分词器支持自定义词典你可以把领域专有名词加进去。# 在IK配置目录下编辑自定义词典 # 容器内路径通常是 /usr/share/elasticsearch/plugins/ik/config/IKAnalyzer.cfg.xml # 在同级目录创建 custom_dict.dic每行一个词比如你做的是AI Agent领域的知识库RAG、Function Calling、Prompt Engineering这些词应该加入自定义词典避免被切碎。改完词典后需要重启ES或者调用reload接口。注意自定义词典的编码必须是UTF-8无BOM格式否则IK读取会乱码。这个坑我踩过排查了半天才发现是词典文件编码问题。5. 实操排查从启动失败到检索异常的完整链路5.1 Docker Compose常见启动问题问题一docker: unknown command: docker compose这个错误说明你的Docker CLI没有Compose插件。检查~/.docker/cli-plugins/目录下是否有docker-compose文件。如果没有重新安装docker-compose-plugin包。Windows上确保Docker Desktop是最新版本。问题二ES容器启动后自动退出最常见的原因是内存不足。ES默认需要至少2GB内存如果ES_JAVA_OPTS没设置或者设置太小容器会OOM退出。查看日志docker compose logs elasticsearch | tail -50如果看到OutOfMemoryError或者bootstrap checks failed调整ES_JAVA_OPTS的-Xms和-Xmx值。开发环境1GB通常够用但要确保宿主机有足够空闲内存。问题三端口冲突9200、6379、8848这些端口如果被占用容器启动会失败。用netstat -tlnp | grep 9200查看端口占用情况然后修改编排文件里的端口映射比如改成19200:9200。5.2 ES连接与版本兼容问题问题this version of the jdbc driver is only compatible with elasticsearch version...这个错误通常出现在用JDBC方式连接ES时。ES 8.x之后官方推荐用REST Client而不是JDBC。如果你用的是Spring Boot确保spring-boot-starter-data-elasticsearch的版本和ES服务端版本匹配。Spring Boot 2.x默认带的ES客户端版本较老连接ES 8.x可能有问题。解决办法是排除默认版本手动引入匹配的客户端依赖。dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-data-elasticsearch/artifactId exclusions exclusion groupIdorg.elasticsearch.client/groupId artifactIdelasticsearch-rest-high-level-client/artifactId /exclusion /exclusions /dependency dependency groupIdco.elastic.clients/groupId artifactIdelasticsearch-java/artifactId version8.12.0/version /dependency问题DBeaver连接ES失败DBeaver连接ES需要安装ES JDBC驱动而且驱动版本要和ES版本匹配。ES 8.x默认开启了HTTPS和认证DBeaver连接时需要配置SSL和用户名密码。如果嫌麻烦开发环境可以临时关闭安全认证但生产环境必须开启。5.3 检索结果异常的排查清单现象可能原因排查方法解决方向中文搜不到结果IK未安装或未生效_analyze测试分词安装IK并重启ES结果排序不合理BM25参数或字段boost问题explain: true查看打分调整boost或k1/b召回率低分词粒度过粗对比ik_smart和ik_max_word索引用max_word精确匹配失效字段类型用了text查看mapping改用keyword类型写入慢磁盘IO瓶颈或merge压力iostat和segment统计换SSD或调merge线程查询超时数据量大或查询太复杂慢查询日志加filter、优化查询结构5.4 几个我踩过的坑和对应技巧坑一ES容器时区不对默认ES容器用的是UTC时间写入的timestamp和本地时间差8小时。解决办法是在编排文件里加TZAsia/Shanghai环境变量或者在应用层统一用UTC时间戳。坑二Docker Compose网络内服务名解析在Compose网络里服务之间可以用服务名互相访问。比如Agent服务连接EShost填elasticsearch而不是localhost。但如果你在宿主机上跑Agent服务连接容器内的EShost要用localhost加映射端口。这个区别搞混了会导致连接失败。坑三数据卷权限问题ES容器内的进程以elasticsearch用户运行UID是1000。如果挂载的宿主机目录权限不对ES会报AccessDeniedException。解决办法是chown -R 1000:1000 ./es_data或者在编排文件里指定user: 1000:1000。坑四IK词典热更新不生效IK支持词典热更新但需要配置remote_ext_dict指向一个HTTP地址。如果只是改了本地词典文件必须重启ES或者调用_reload接口。很多人改了词典发现没效果就是因为忘了这一步。# 重新加载IK词典需要ES开启reload API curl -X POST http://localhost:9200/_ik/_reload6. 从开发到部署的完整工作流建议6.1 本地开发环境的最小化配置本地开发不需要把整个技术栈都拉起来。我的建议是ES和Redis用Docker Compose起Agent主服务在IDE里直接跑。这样调试方便改代码即时生效不用重新构建镜像。.env文件管理环境变量# .env ES_HOSTlocalhost ES_PORT9200 REDIS_HOSTlocalhost REDIS_PORT6379 REDIS_PASSWORDagent123Compose文件里引用这些变量应用配置里也引用保证一致性。6.2 测试环境的编排调整测试环境需要更接近生产。ES至少两个节点Redis开启持久化Nacos用集群模式。但资源消耗也相应增加。如果测试机配置有限可以只把ES做成两节点其他服务保持单节点。# 测试环境ES两节点配置片段 services: es01: image: docker.elastic.co/elasticsearch/elasticsearch:8.12.0 environment: - node.namees01 - cluster.nameagent-cluster - discovery.seed_hostses02 - cluster.initial_master_nodeses01,es02 - xpack.security.enabledfalse - ES_JAVA_OPTS-Xms2g -Xmx2g # ... 其他配置 es02: image: docker.elastic.co/elasticsearch/elasticsearch:8.12.0 environment: - node.namees02 - cluster.nameagent-cluster - discovery.seed_hostses01 - cluster.initial_master_nodeses01,es02 - xpack.security.enabledfalse - ES_JAVA_OPTS-Xms2g -Xmx2g # ... 其他配置6.3 生产环境的注意事项生产环境有几条硬性要求ES必须开启安全认证、必须配置至少三个master节点避免脑裂、必须设置监控和告警、必须有数据备份策略。ES的安全认证配置涉及证书生成步骤较多。简单说就是用elasticsearch-certutil生成CA和节点证书然后在编排文件里挂载证书目录配置xpack.security.enabledtrue和xpack.security.transport.ssl.enabledtrue。监控方面ES自带的_cluster/health和_nodes/stats可以接入Prometheus。关键告警指标包括集群状态非green、JVM堆内存使用率超过85%、磁盘使用率超过80%、写入拒绝数大于0。数据备份用ES的snapshot API定期快照到对象存储或共享文件系统。恢复时用restore API。这个流程建议在测试环境演练一遍确保真出问题时能快速恢复。6.4 性能调优的几个实用参数参数默认值建议值说明index.refresh_interval1s30s写入密集时降低refresh频率提升写入吞吐index.translog.durabilityrequestasync可容忍少量丢失时异步translog提升写入性能index.merge.scheduler.max_thread_count自动磁盘IO强时调大加快段合并thread_pool.write.queue_size10000根据负载调整写入队列大小indices.memory.index_buffer_size10%20%写入密集时索引buffer大小这些参数不是越大越好需要根据实际负载测试。我的经验是先在默认配置下压测找到瓶颈后再针对性调整每次只改一个参数观察效果。6.5 一个完整的检索请求示例最后给一个完整的检索请求包含BM25打分、字段boost、过滤条件和分页curl -X POST http://localhost:9200/agent_knowledge/_search -H Content-Type: application/json -d { query: { bool: { must: [ { multi_match: { query: Docker Compose 部署 ES, fields: [title^3, content^1], type: best_fields, operator: or } } ], filter: [ { term: { doc_type: tutorial } }, { range: { created_at: { gte: 2024-01-01 } } } ] } }, highlight: { fields: { content: {} } }, from: 0, size: 10, _source: [title, doc_type, created_at] }这个请求会在title和content里搜关键词标题权重是内容的三倍过滤出doc_type为tutorial且创建时间在2024年之后的文档返回高亮片段分页取前10条只返回指定字段减少网络传输。实际项目中我会把这类查询封装成Java或Python的方法参数化query、filters、page、size方便复用和测试。ES的查询DSL很灵活但也容易写错建议每个查询都先用curl验证再集成到代码里。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

飞猪帮帮交付可用率提升70%,携程问道还停在聊天框:三大OTA AI Agent谁在认真做事 2026/9/28 18:21:46

飞猪帮帮交付可用率提升70%,携程问道还停在聊天框:三大OTA AI Agent谁在认真做事

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
从零手写 ClaudeCode 实战笔记(2)Tool Use:用 dispatch map 搭出可复制的工具调用骨架 2026/9/28 18:21:46

从零手写 ClaudeCode 实战笔记(2)Tool Use:用 dispatch map 搭出可复制的工具调用骨架

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
用 TaoToken 统一 Key 抓取桌面窗口信息:句柄、类名与缩略图 API 实战 2026/9/28 18:21:46

用 TaoToken 统一 Key 抓取桌面窗口信息:句柄、类名与缩略图 API 实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
Solr 深度分页实战:用 cursorMark 替代 start 翻页的配置与验证 2026/9/28 18:21:46

Solr 深度分页实战:用 cursorMark 替代 start 翻页的配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
深入解析 MCP Server 实现原理与实战开发指南:TaoToken 统一 Key 接入配置骨架 2026/9/28 18:21:46

深入解析 MCP Server 实现原理与实战开发指南:TaoToken 统一 Key 接入配置骨架

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
Modelsim 光标测量时间间隔:TaoToken 统一 Key 接入 settings.json 配置与验证 2026/9/28 18:21:33

Modelsim 光标测量时间间隔:TaoToken 统一 Key 接入 settings.json 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉