码农戏码

新生代农民工的自我修养

0%

继续排盘软件开发,最近把格局的能力也加上。

直接让AI自己去分析一下什么是格局,以及怎么取

最后的效果是这样的:

看着AI真是啥都知道,先不论对错,说是的有模有样

一句话结论

格局以月令为核心,透干为优先,清纯为贵,成败看全局。

也就是说:

  1. 先看月令是什么
  2. 再看月令所藏之神有没有透出天干
  3. 再看这个“格神”有没有根、有无帮扶、是否被破坏
  4. 最后再看全局能不能成“局”,再谈用神喜忌。

一、先分清“格”和“局”

这两个词经常连在一起说,但其实不是一回事:

  • :偏重“月令主什么”,也就是命局的主导十神从哪里立出来;
  • :偏重“全盘有没有配合成势”,也就是这个格能不能成立、能不能发挥。

可以粗略理解为:

  • = 立题目
  • = 看这道题有没有做成

所以程序上、分析上都建议按这个顺序:

先取格,再判局,最后定用神。


二、主流子平法的取格顺序

1. 以日主为参照,看月令藏干对应什么十神

格局不是脱离日主单独看的。

比如:

  • 甲日主 来说,辛是正官、庚是七杀、己是正财、戊是偏财;
  • 丙日主 来说,戊是食神、己是伤官、癸是正官、壬是七杀。

所以“格”到底是什么,必须先把月令藏干换算成日主的十神


2. 先看“月令所藏之神是否透干”

这是取格的核心。

常见原则

  • 月令本气透出,最容易立格;
  • 月令中气、余气透出,如果本气不透、而透出的那个神又得令得势,也可以立格;
  • 月令多神同透,不能见一个就立一个,要看谁更当令、谁更清纯、谁更能主事。

口诀化理解

月令是根,透干是门。

月令里有这个东西,只是“藏着”;
透到天干,才算“出来做事”。

所以传统上常说:

有令有透,方能真立格。


3. 透者为先,本气为重

如果月令里有多个藏干,优先级通常是:

  1. 本气透干
  2. 中气/余气透干,但明显得势
  3. 都不透,则回到月令本气或当令之气

例如辰、戌、丑、未这类“杂气月”,最容易出现多个候选。
这时不能只看“月支里有什么”,还要看:

  • 谁透出来了;
  • 谁正在得令;
  • 谁在全局中有根;
  • 谁没有被严重冲克。

4. 月令不透时,仍以月令主气为主

有些八字月令之神完全不透,但也不能因此说“没有格”。

这时常见处理是:

  • 先按月令本气取格
  • 若月令是杂气、且出生日期正好落在分金用事阶段,则可参考司权之神做细化判断;
  • 但一般不建议完全抛开月令主气,只按别处旺衰硬立格。

这点和仓库里已有的《月令分金》文档可以配合看。


三、月令分金在“取格”里怎么用

这个项目里已经整理了“月令分金(人元司令分野)”,这对精细取格很有帮助。

但要注意:

  • 月令主气,仍然是定格的大前提;
  • 司权用事,更像是对月令内部轻重的细分;
  • 它适合做“候选格排序”和“杂气月细化”,不一定是完全取代月令本气。

实务上可以这样理解

简法

  • 不细分出生在本月第几天;
  • 直接按月支本气取格;
  • 适合快速排盘和基础分析。

细法

  • 结合节气后第几天,确认当前是余气、中气还是本气在司权;
  • 特别适合寅、辰、巳、未、申、戌、亥、丑这些多藏干月份;
  • 可用于解释“为什么同月不同日,取格重点略有不同”。

一个例子

假设 丙日主生辰月

  • 辰中藏 戊、乙、癸
  • 对丙来说,戊是食神,乙是正印,癸是正官;
  • 如果戊透出,可优先看食神格
  • 如果癸透出且官星清纯,也可能按官格看;
  • 如果都不透,而出生又落在辰月后段、戊土司权明显,则更偏向按食神格/杂气食神去理解。

所以分金的价值,在于帮助判断:

月令里面,到底是谁在“当前主事”。


[[使用ExecutorServiceMetrics对线程池进行监控]]

为了实现这个目标,就让AI进行代码生成,生成得还不错,还自己加戏做了一些额外工作

自定义了一些tag,看着应该有用

1
2
3
4
5
6
private Iterable<Tag> buildTags(String poolType) {  
return Tags.of(
"thread.pool.source", "ThreadPoolUtil",
"thread.pool.type", poolType
);
}
1
2
Iterable<Tag> tags = buildTags(poolType);  
new ExecutorServiceMetrics(executor, poolName, tags).bindTo(meterRegistry);

/actuator/prometheus 中应该能持续看到类似指标:

1
2
3
4
5
executor_active_threads{...,name="Test_xxx",thread_pool_source="ThreadPoolUtil",thread_pool_type="Test"} 1.0
executor_pool_core_threads{...,name="Test_xxx",thread_pool_source="ThreadPoolUtil",thread_pool_type="Test"} 25.0
executor_pool_max_threads{...,name="Test_xxx",thread_pool_source="ThreadPoolUtil",thread_pool_type="Test"} 25.0
executor_queued_tasks{...,name="Test_xxx",thread_pool_source="ThreadPoolUtil",thread_pool_type="Test"} 0.0
executor_completed_tasks_total{...,name="Test_xxx",thread_pool_source="ThreadPoolUtil",thread_pool_type="Test"} 0.0

理想很美好,现实却打脸。在/actuator/prometheus一直没有看到收集到的指标

让AI再分析一下,给了几个猜测

结合当前代码实现,最常见原因通常不是“完全没绑定”,而是以下几类问题:

  1. 查询的指标名不对
  2. 线程池生命周期太短,抓取时已经结束
  3. 实际线程池没有走 ThreadPoolUtil.createFixedThreadPool(...)
  4. binder 没有真正初始化成功

看着第2点,有点道理。防止他在不停地怀疑1、3、4,他不相信人类,只能让他自己干了,让他自己写测试代码进行测试。


分析一通后,又开始猜测了

最可能根因:同名 executor.* 指标的 label 集不一致,Prometheus 无法合并

Prometheus 对同一个 metric family 有一个重要要求:

  • 同名指标的所有时间序列,label key 集合必须一致

也就是说,如果同一个指标名下有两组数据:

第一组

1
executor_active_threads{application="north",name="csmThreadPoolTaskExecutor"} 1

第二组

1
2
3
4
5
6
executor_active_threads{
application="north",
name="Test_xxx",
thread_pool_source="ThreadPoolUtil",
thread_pool_type="Test"
} 0

那么这两组数据的 label key 并不一致:

第一组 label key

  • application
  • name

第二组 label key

  • application
  • name
  • thread_pool_source
  • thread_pool_type

这会导致同一个 executor_active_threads family 出现 label schema 冲突


为什么项目里很可能已经存在另一组 executor.* 指标

Spring Boot 2.7 自带:

  • TaskExecutorMetricsAutoConfiguration

它会自动为 Spring 容器里的 ThreadPoolTaskExecutor / ThreadPoolTaskScheduler 绑定 ExecutorServiceMetrics

本项目里已经存在多个 ThreadPoolTaskExecutor Bean,

Spring Boot 的自动绑定方式相当于:

1
new ExecutorServiceMetrics(threadPoolExecutor, beanName, Collections.emptyList()).bindTo(registry);

也就是说,这批自动注册的 executor.* 指标通常只有:

  • name
  • 再加全局 common tags(如 application

它们没有

  • thread.pool.source
  • thread.pool.type

自己拉屎,自己再吃

推荐修复方案

针对这个问题,推荐优先使用以下方案。

方案一:给 ThreadPoolUtil 指标加独立 metric prefix(最推荐)

不要继续使用默认的:

  • executor.*

而是改成带前缀的独立指标族,例如:

  • threadpoolutil.executor.*
  • north.threadpool.executor.*

代码上可以改为:

1
new ExecutorServiceMetrics(executor, poolName, "threadpoolutil", tags).bindTo(meterRegistry);

这样 Micrometer 原始名会变成:

  • threadpoolutil.executor.active
  • threadpoolutil.executor.completed

在 Prometheus 中会变成类似:

  • threadpoolutil_executor_active_threads
  • threadpoolutil_executor_completed_tasks_total

这样它就不会和 Spring Boot 自动注册的:

  • executor_active_threads

发生 metric family 冲突。

这是最推荐方案,因为它:

  • 保留了 thread.pool.source
  • 保留了 thread.pool.type
  • 避免和已有 executor 指标同名冲突

方案二:去掉额外 tag,仅保留与默认 executor 指标一致的标签集

也可以把自定义 tags 去掉,改成只保留默认的:

  • name

这样就能和 Spring Boot 自动线程池指标共用同一个 family。

但缺点是:

  • 无法区分这些指标是否来自 ThreadPoolUtil
  • 无法直接按 thread_pool_type 做筛选

所以一般不如方案一。

当前处理结果

本次已经按方案二落地:

  • ThreadPoolExecutorMetricsBinder 不再为 ThreadPoolUtilexecutor.* 指标附加:
    • thread.pool.source
    • thread.pool.type
  • 改为只使用 ExecutorServiceMetrics 的默认标签集

这样做的直接效果是:

  1. ThreadPoolUtil 创建的线程池指标可以和 Spring Boot 自动注册的 executor.* 指标使用同一套 label key
  2. /actuator/prometheus 中不再因为 label schema 不一致导致 family 冲突
  3. 查询时应主要通过 name="Test_xxx" 来定位对应线程池

也就是说,修复后 Prometheus 中应按下面方式检索:

1
curl -s http://localhost:8088/actuator/prometheus | grep 'name="Test_'

而不是再按:

1
thread_pool_type="Test"

因为方案二落地后,这两个额外标签已经被移除。


方案三:统一全项目所有 executor 指标的 label 结构

理论上也可以让所有 executor.* 指标都带同样的 label keys。

但这意味着:

  • 要覆盖 Spring Boot 自动注册逻辑
  • 或自己接管所有线程池指标绑定

实现复杂度高,不适合作为当前问题的首选方案。


最后选择了方案二,把label key统一。还真成功了。

这次使用的 gpt-5.4 high 模型,感觉就差一口气。就不让一开始就规避这个低级错误吗?

是不是故意烧点token

最近想对线程池增加一下监控,先从https://grafana.com/grafana/dashboards/ 找到一个关于Spring Boot Executors的Grafana面板

尽然发现,已经有部分线程池被监控到了,记得以前都得使用ExecutorServiceMetrics包装一下,原来在Springboot 2.6.0版本提供了TaskExecutorMetricsAutoConfiguration,可以自动给线程池加上metrics

TaskExecutorMetricsAutoConfiguration

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@AutoConfiguration(after = { MetricsAutoConfiguration.class, SimpleMetricsExportAutoConfiguration.class,  
TaskExecutionAutoConfiguration.class, TaskSchedulingAutoConfiguration.class })
@ConditionalOnClass(ExecutorServiceMetrics.class)
@ConditionalOnBean({ Executor.class, MeterRegistry.class })
public class TaskExecutorMetricsAutoConfiguration {

@Autowired
public void bindTaskExecutorsToRegistry(Map<String, Executor> executors, MeterRegistry registry) {
executors.forEach((beanName, executor) -> {
if (executor instanceof ThreadPoolTaskExecutor) {
monitor(registry, safeGetThreadPoolExecutor((ThreadPoolTaskExecutor) executor), beanName);
}
else if (executor instanceof ThreadPoolTaskScheduler) {
monitor(registry, safeGetThreadPoolExecutor((ThreadPoolTaskScheduler) executor), beanName);
}
});
}

看源码,原理跟之前手动操作一样遍历executors,然后执行monitor方法,而monitor方法则是创建ExecutorServiceMetrics然后绑定到meterRegistry

ExecutorServiceMetrics

ExecutorServiceMetrics 是 Micrometer 中专门用于监控 Java 线程池(ExecutorService)的工具。它可以帮助你实时了解线程池的运行状态,比如活跃线程数、队列积压、任务执行耗时等,这些指标对排查性能问题和优化线程池配置很有价值。

核心的使用方法有两种:直接包装(推荐)构造器绑定

📊 暴露的监控指标

指标名称会根据你的线程池类型(ThreadPoolExecutorForkJoinPool)略有不同:

指标名称 类型 描述
executor.active Gauge 当前正在执行任务的活跃线程数
executor.queued Gauge 队列中等待执行的任务数量
executor.completed FunctionCounter 线程池已完成的任务总数
executor.pool.size Gauge 线程池中当前的线程总数
executor Timer 记录任务执行的耗时分布(P99、P95等)
executor.idle Timer 记录任务在队列中的等待耗时
executor.queue.remaining Gauge 队列剩余容量(ThreadPoolExecutor 特有)
executor.steals FunctionCounter 工作窃取总数(ForkJoinPool 特有)

🛠️ 使用步骤

1. 添加依赖

确保你的项目中引入了 Micrometer 的核心依赖。

1
2
3
4
5
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-core</artifactId>
<version>最新版本</version>
</dependency>

2. 方法一:直接包装(monitor 方法)

这是最常用的方式。monitor 方法会返回一个被 Micrometer 增强过的 ExecutorService 代理对象。你只需要像平常一样用它提交任务即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.binder.jvm.ExecutorServiceMetrics;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ExecutorMonitorDemo {

private ExecutorService monitoredExecutor;

public ExecutorMonitorDemo(MeterRegistry registry) {
// 1. 创建原始的线程池
ExecutorService originalExecutor = Executors.newFixedThreadPool(10);

// 2. 用 Monitor 方法进行包装
// 参数说明:MeterRegistry, 原始Executor, 线程池名称(用于标签), 可选的额外标签
this.monitoredExecutor = ExecutorServiceMetrics
.monitor(registry, originalExecutor, "my-service-pool");

// 3. 使用被包装过的线程池执行任务
monitoredExecutor.submit(() -> {
System.out.println("Task is being monitored!");
});
}
}

3. 方法二:构造器绑定(bindTo 方法)

这种方式只注册指标,不返回代理对象。适用于你不想改变现有线程池引用的情况。

1
2
3
4
5
6
7
8
9
10
11
12
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.binder.jvm.ExecutorServiceMetrics;
import io.micrometer.core.instrument.Tags;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;

// 假设你已有一个 threadPool 实例
ThreadPoolExecutor threadPool = (ThreadPoolExecutor) Executors.newFixedThreadPool(5);

// 创建 ExecutorServiceMetrics 实例,并绑定到 MeterRegistry
new ExecutorServiceMetrics(threadPool, "my-pool-name", Tags.empty())
.bindTo(registry);

对于Agent的价值,一直抱有怀疑态度,甚至认为未来会不会像大前端一样

别看现在火爆得不行,其实再走到下一个节点,就如前端一样,在裁员批次里面是第一梯队

因为它只是个连接器,一端是大脑LLM,另一端是承载业务的平台或专业软件,它自己本身对业务没有任何承载。

或者说它只是LLM的一个外延,也许未来会有其它的形式

之前想到的一个价值,就类似客服一样,可以帮助客户或者实施更快捷地接入产品,使用产品。

像一个垂直类专业软件,需要花费很多的资源去培训客户,但如果有了agnet,通过自然语言直接对话,都不需要去学习软件的使用,就能产出相应的结果

有点类似后端程序,可能都不清楚产品前端界面是什么样,开发一个个接口逻辑就行了。

但还不够具象。

在看到arthas也出品了agent,这感觉具象化了,对于arthas 我是实实在在的使用客户。

以前你需要去学习arthas的各种命令,会安装一下IDEA 的插件,直接能复制生成出相应完整命令行,再去执行。

但有了agent 那就更方便了,什么都不需要,把碰到的问题直接使用自然语言抛给agent,它能帮你分析,帮你执行命令。相当方便

本来打算学习一下arthas agent,结果agent也没对外开源,只是阿里内部使用。

不过对外开源了mcp server,自己搭agent

https://arthas.aliyun.com/doc/mcp-server.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
mcp:  
client:
enabled: true
type: sync
name: north-agent
version: 1.0.0
request-timeout: 15s
toolcallback:
enabled: true
streamable-http:
connections:
arthas-mcp:
url: http://localhost:8563
endpoint: /mcp

直接创建一个SKILL.md

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
---
name: arthas-diagnosis
description: 用于 Arthas MCP 诊断任务,包括 JVM 信息查看、线程分析、类加载器排查、方法跟踪、性能采样和文件结果读取。
---

# Arthas 诊断技能

这是面向运行时诊断与排障的专用技能。

## 什么时候使用

- 用户明确提到 `Arthas`、`JVM`、`线程`、`堆`、`类加载器`、`trace`、`watch`、`profiler`
- 用户要做运行时排障、性能分析、线程阻塞分析、类加载问题诊断
- 用户希望读取 Arthas 导出的诊断结果文件

## 核心原则

- 这是诊断域技能,不要和 Lot / CPE 业务操作混用
- 当前环境中的诊断能力来自 **arthas-mcp 已注册工具**,不要假设存在本地 Arthas CLI、`arthas-boot.jar`、JVM attach 权限或 shell 执行能力
- 只能调用当前 skill 已挂载的 MCP 工具;不要编造不存在的工具名,例如 `run_arthas_command`
- 不要读取或引用不存在的示例文件;若用户没有提供真实文件路径,不要假设如 `dashboard_sample_output.txt` 之类的本地样例文件存在
- 先做只读诊断,再做可能影响运行时状态的动作
- 如果用户目标不明确,先澄清要排查的是:线程、内存、类、方法调用、还是性能
- 优先使用风险更低、范围更小的工具

## 可直接使用的工具类型

本技能应直接使用 arthas-mcp 暴露出来的工具,例如:

- 概览:`dashboard`、`jvm`、`memory`、`thread`
- 类诊断:`sc`、`sm`、`classloader`、`jad`
- 方法诊断:`stack`、`trace`、`watch`、`monitor`、`tt`
- 性能分析:`profiler`
- 文件读取:`viewfile`

效果还可以,后面分析一下arthas相关源码,里面的实现很是精巧,有意思!

最近在给排盘软件增加一下神煞的功能

首先神煞命中分成两个太极点:年和日

  • 年取:以年柱为太极点去查
  • 日取:以日柱为太极点去查

然后基本流程是:
1、先确认神煞的查法和作用
2、把介绍、查法和作用都整理输出到文档
3、再根据文档里面的逻辑变成代码逻辑
4、再确认是否展示到UI
5、又增加一项,点击神煞时,会弹出神煞介绍

刚开始手动完成了 三丘五墓、桃花

后来想起这是一套标准动作,以后增加新的神煞时,都需要这么跟AI交互。

这不就是skill吗? 所以就让codex直接创建一个扩展神煞的skill

按这个套路,创建一个 skill,方便后面增加其他的神煞

完成之后,会创建相应的SKILL.md

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
---
name: extend-mingli-shensha
description: Add or update shensha logic in the mingli repo, including rule documentation, utility functions, explanation/method text, and UI display. Use when Codex needs to add a new 神煞, adjust an existing 神煞’s取法 or作用, wire it into src/utils/shensha.ts, update docs/shensha-*.md and docs/shensha-overview.md, or connect it to the App.tsx/App.css display and popup flow.
---

# Extend Mingli Shensha

Implement new shensha in this repo with the same pattern already used for 驿马、桃花、羊刃、禄、天乙贵人、三丘五墓.

## Quick workflow

1. Read `docs/shensha-overview.md` first.
2. If the target shensha already has a dedicated doc, read `docs/shensha-*.md`; otherwise create one before coding.
3. Implement or update logic in `src/utils/shensha.ts`.
4. If the shensha should appear in the UI, wire it into `src/App.tsx` and `src/App.css`.
5. If the shensha needs click-to-explain support, add explanation and method text in `src/utils/shensha.ts`.
6. Run `npm run build` before finishing.

这个skill就叫 extend-mingli-shensha

用这个skill,试一下增加文昌神煞

extend-mingli-shensha to add 文昌的规则、文档和展示

中途不再需要跟AI不停地交互,完整按标准动作完成了整个神煞的整理和开发工作

最后展示的效果也还不错

最近在项目中引入skill

把之前需要在系统提示词中注明的规则,全面挪移到相应skill的 SKILL.md 说明文件中

不过AI迭代太快,Spring Ai Alibaba 文档都来不及更新,里面的bug也不少。

在本地功能测试没有问题,发布到服务器,发现Skill not found: Skill not found: lot-query

1
2
3
4
5
6
7
8

INFO 1 --- [oundedElastic-1] c.a.c.ai.graph.agent.node.AgentLlmNode : [ThreadId 07f735f0-fd80-49b8-b4e5-7e90cfc2eb35] Agent ??? reasoning round 0 streaming output: [ToolCall[id=call_03da1a646a1a410bb82cf6, type=function, name=read_skill, arguments={"skill_name": "lot-query"}]]
2026-03-17T03:01:57.046330027Z 2026-03-17T11:01:57.046+08:00 INFO 1 --- [oundedElastic-1] c.a.c.ai.graph.agent.node.AgentToolNode : [ThreadId 07f735f0-fd80-49b8-b4e5-7e90cfc2eb35] Agent ??? acting with 1 tools.
2026-03-17T03:01:57.048982723Z 2026-03-17T11:01:57.048+08:00 INFO 1 --- [oundedElastic-1] c.a.c.ai.graph.agent.node.AgentToolNode : [ThreadId 07f735f0-fd80-49b8-b4e5-7e90cfc2eb35] Agent ??? acting, executing tool read_skill.
2026-03-17T03:01:57.050245886Z 2026-03-17T11:01:57.050+08:00 WARN 1 --- [oundedElastic-1] c.a.c.a.g.a.hook.skills.ReadSkillTool : **Skill not found: Skill not found: lot-query**
2026-03-17T03:01:57.051826871Z 2026-03-17T11:01:57.051+08:00 INFO 1 --- [oundedElastic-1] c.a.c.ai.graph.agent.node.AgentToolNode : [ThreadId 07f735f0-fd80-49b8-b4e5-7e90cfc2eb35] Agent ??? acting, tool read_skill finished
2026-03-17T03:01:57.053390410Z 2026-03-17T11:01:57.052+08:00 INFO 1 --- [oundedElastic-1] c.a.c.ai.graph.agent.node.AgentToolNode : [ThreadId 07f735f0-fd80-49b8-b4e5-7e90cfc2eb35] Agent ??? acting returned: ToolResponseMessage{responses=[ToolResponse[id=call_03da1a646a1a410bb82cf6, name=read_skill, responseData="Error: Skill not found: lot-query"]], messageType=TOOL, metadata={messageType=TOOL}}

原来是框架里面的ClasspathSkillRegistry 在Spring Boot fat jar 场景中有bug,会加载不到SKILL.md 文件

  1. 打包后的 jar 中已经确认包含 skill 文件,例如:
    • BOOT-INF/classes/skills/cpe-operation/SKILL.md
    • BOOT-INF/classes/skills/lot-operation/SKILL.md
    • BOOT-INF/classes/skills/lot-query/SKILL.md
    • BOOT-INF/classes/skills/true-north-router/SKILL.md
  2. 但应用启动日志显示:
    • TrueNorth skill registry loaded 0 skills.
    • TrueNorth skill registry is empty at startup.
  3. 随后模型调用 read_skill("lot-query") 时,得到:
    • Skill not found: lot-query

使用AI分析了一下源码,现在有AI 学习效率提升不少,以前还要手动翻源码,画流程图,清楚调用关系。

现在先让AI分析一下源码,输出各种结构图,快速梳理出框架主干

再针对性提问题,让他提出源码位置,细节一目了然

把AI分析结果提交个issue: https://github.com/alibaba/spring-ai-alibaba/issues/4426

再让AI重新实现一个SkillRegistry,解决这个问题

项目中有一个参数cpeModel ,是固定的枚举项,希望在大模型询问参数时,给出固定的选项,在
Tool 参数上,描述一下:

1
@ToolParam(description = "必须让用户确认选择cpeModel,可选值只能是CPE2;CPE6;CPE6CF9;CPE15;CPE15CF4;CPE19其中一个") @NotNull String cpeModel

这样就达到了效果,从没有出现幻觉现象。

最近在项目中引入skill,系统提示词大幅减小,却出现了幻觉

模型输出类似:

  • CD65_CPE_Standard
  • CD65_CPE_Advanced
  • CD65_CPE_Quality
  • CPEv2
  • CPEv3
  • CPE-AI

从当前项目代码和 skill 契约来看,这些都不是正式允许值,因此属于幻觉式扩展

这就奇怪,现在的Tool定义上也有,而且在SKILL.md文件中也特意说明

1
2
3
4
5
6
7
8
9
10
11
12
如果用户尚未提供 `cpeModel`,你必须只展示正式允许值列表,并要求用户从中选择。
禁止补充任何额外示例、行业常见名、产品名、历史名、猜测值,禁止使用“常见模型包括”“例如”“或者其他模型名称”这类会诱导扩展的表达。

固定回答格式:

请从以下正式 cpeModel 中选择一个:
- CPE2
- CPE6
- CPE6CF9
- CPE15
- CPE15CF4
- CPE19

虽然这样写了,但有时还是会幻觉,特地还写了一个tool,强制输出枚举项

在SKILL.md里面写上当需要枚举参数确认时,调用这个tool来确认

可过两天测试又正常了,不再需要这个参数确认的tool

最近又有一个新词叫:Harness Engineering

Prompt Engineering管的是「说什么」,Context Engineering管的是「知道什么」,Harness Engineering管的是「在什么环境里做事」

技术上来说,Harness 是包裹在 AI Agent 外面的那层基础设施,负责管理:

  • 工具调用(Tool Use)

  • 上下文记忆(Context / Memory)

  • 错误重试(Retry)

  • 人工审批节点(Human-in-the-loop)

  • 架构约束和代码规范检查

主要就是来应对模型的幻觉和执行的漂移

模型的幻觉
指模型生成内容时,编造出看似合理但事实上错误、无依据的信息。

  • 根源:大模型本质是概率生成器,它在“续写”时没有内置的事实核查机制;训练数据中的偏差、知识截止后的新事实、过度自信的生成都会导致幻觉。

  • 表现:在事实性问答、代码生成、逻辑推理中常见,尤其在模型不确定时反而会“自信地胡说”。

执行的漂移
指在复杂任务(尤其是多步、长周期、与环境交互的任务)中,模型逐渐偏离原始目标、违反约束或进入无效状态。

  • 根源:自回归误差累积、缺乏全局规划、对中间反馈的误判。

  • 表现:例如Agent在调用API时循环调用、智能体在完成多步任务时忘记最初指令、模型输出逐渐超出安全边界等。

最近笔记转换到了Obsidian,所以想开发了一个Obsidian插件

震求很简单,把Obsidian里面的笔记一键发布到公众号,在这个里面有个小的需求,需要把mermaid图转换成图片自动上传微信

类似hexo中的hexo-filter-mermaid-diagrams插件

hexo-filter-mermaid-diagrams 是一个用于 Hexo 的 Mermaid 插件。

它的核心思路不是“在构建时把 Mermaid 转成最终图片”,而是:

在页面中注入 Mermaid 脚本,等博客页面加载后,由浏览器再去渲染 Mermaid 图表。

但公众号里面不能这处理

微信公众号复制场景有个关键限制:

  • 粘贴到公众号编辑器后,不能依赖额外脚本继续执行 Mermaid

比如一个流程图:

Mermaid 自定义样式渲染修复

问题:Mermaid 图表中使用 style 指令自定义节点颜色(如 style B fill:#e1f5fe)时,导出到 PNG 后节点显示为黑色背景,丢失自定义填充色。

根本原因

  • Mermaid 将自定义样式写入 SVG 元素的 inline style 属性
  • Canvg 在光栅化时无法正确处理 inline style 的 CSS 优先级
  • <style> 块中的默认主题规则(如 .node rect { fill: #ECECFF; })覆盖了自定义样式

解决方案

  1. 保留 <style> 块(默认节点依赖它提供填充色和边框)
  2. 提取 inline style 中的 SVG 属性(fill、stroke 等)
  3. 为包含自定义样式的元素添加唯一 CSS 类
  4. 将提取的属性以 !important 规则追加到 <style> 块末尾
  5. 同时设置 SVG presentation attributes 作为兜底

这样既保证默认节点的样式完整,又通过 CSS 优先级确保自定义样式正确渲染。

使用 Claude Opus 4.6 模型

使用gpt-5.3-codex 和 gpt-5.4 模型

这么一个需求,模型知错、认错的功夫杠杠的,但就是改不了错

模型切了好几个,token花费不少,可最终问题还是没有完美解决

Agent 架构的演化逐渐分化出了四条最主要的路径:“Single Agent → Multi-Agent  → Agent Skills → Agent Teams”

Agent架构为什么需要演化,就是因为我们在 基础大模型无法完美内化“领域知识”和高效复用“长期记忆” 的背景下,不断尝试“外挂”出这些能力的。

本质上就是大家对大模型如何更好的注入领域知识和记忆管理这两方面的需求,不断促进了Agent架构的演化。

Single Agent架构

Single Agent指的是“狭义的”基于ReAct的自主Agent概念,使用System Prompt驱动、串行调用工具的原生Agent运行模式

核心逻辑

既然大模型无法直接内化我们特定的领域知识,那我们就通过System Prompt的方式,将这些知识“无脑”地注入到大模型的上下文中,期望它能基于这些注入的信息生成符合预期的答案。

你只需要将领域知识整理好,配合清晰的指令写入系统级指令的System Prompt中,再使用基础模型原生的ReAct模式自主调用工具、记录上下文并解决问题。

对于生成简单的代码段、写文案、执行某类标准化输出等场景,这种串行调用的单Agent模式往往能跑出最流畅的体验,是验证想法、ROI最高的原型方案

优势

实现简单、开发快、运行效率高,适合快速验证和简单场景。

劣势

上下文窗口易爆炸:注入海量知识会导致“关键信息遗忘”(Lost in the Middle)问题

长上下文并不等于长记忆。当输入数据量达到一定阈值时,模型极易出现“Lost in the Middle”问题,也就是“注意力缺失”或者“关键信息遗忘”的现象,导致其无法精准定位到所需的领域知识,最终输出的结果偏离预期

解决方案

行业普遍采用的解决方案是引入 RAG(检索增强生成)

[[RAG是什么]]

RAG 可以看作是在Single Agent基础上的一次重要演进。它的核心逻辑是“先搜后答”:在将知识注入大模型之前,先利用搜索工具进行一轮召回(Recall),仅将与用户问题相关度最高的那部分片段提取出来,作为上下文提供给 Agent。

这在一定程度上巧妙规避了 Context Window 的长度限制,让 Agent 能够“按需获取”知识,而非“全量吞咽”。然而,RAG架构的效果存在一个致命的依赖链——“垃圾进,垃圾出”(Garbage In, Garbage Out)。Agent 的 最终表现高度依赖于前置搜索环节的准确率。如果检索阶段未能召回正确的知识片段,无论后端的大模型能力多强,都无法生成正确的答案

flowchart TD
    A["用户问题
(例如:ECS远程连接失败?)"] --> B["嵌入模型
(小模型)"] B --> C["将问题转化为
向量"] C --> D["向量数据库
(存储着海量领域知识)"] D --> E{"相似性检索"} E --> F["召回 Top-K 个
最相关的知识片段"] F --> G["提示词组装"] G --> H["将问题 + 召回片段
组合成最终提示词"] H --> I["大语言模型
(LLM)"] I --> J["生成最终答案"] style A stroke-width:2px style B fill:#e1f5fe,stroke:#01579b style I fill:#fff9c4,stroke:#fbc02d style J stroke-width:2px

Reference

《Agent/Skills/Teams 架构演进过程及技术选型之道》

“虚中法”“子平法”学习框架

这份文档是一位命理老师在讲解八字命理学的核心框架与学习方法,内容详实,情绪激昂,旨在为学生厘清思路、夯实基础。以下是详细的内容总结:

一、核心思想与总论

  1. 强调基础的重要性:反复告诫学生不要追求“秘诀”,命理学博大精深但没有秘密,真正的核心都在经典之中。学习的关键在于“打基础”,必须反复研读经典和上课视频。

  2. 命理学的两大体系:明确指出八字命理主要分为 “虚中法”“子平法”,二者视角不同,但需要结合使用。

    • 虚中法(禄命法):以 年柱 为太极点(核心),论 先天之命。核心是“禄、命、身”加上神煞。看的是一个人与生俱来、命中注定的福禄、根基、体质等。

    • 子平法:以 日柱(日元) 为太极点,论 后天之运。核心是 月令格局 加上神煞。看的是一个人出生后,在具体的人伦社会中如何获取财富、地位、婚姻、子女等。

  3. “主本同参”原则:这是核心方法论。必须将 年柱代表的先天命日柱代表的后天运 结合起来看,不可偏废。先天命是根基,后天运是发挥。后天所得若与先天年柱的禄马贵气等呼应,则福大贵大;若脱节,则福贵减小。

二、具体方法论详解

  1. 论六亲

    • 年柱定六亲:决定命里“有没有”、先天缘分厚薄(“命里有时终须有”)。

    • 日柱定六亲:决定后天在社会中“如何得到”、关系相处的具体状态。

    • 二者需协调参看。

  2. 论婚姻

    • 主要看 日支(夫妻宫)月支

    • 同时必须结合 命宫 来起“十二宫”,其中 命宫的对宫就是夫妻宫。论婚姻时,要确保日支/月支的夫妻宫与十二宫的夫妻宫 不可交战,并综合查看两宫的神煞。

  3. 其他重要概念与用法

    • 胎元、胎息、胎变:三者与胎元所在之年,构成 “先天八字”。此盘不看十神,主要看地支的刑、冲、破、害,以及字形(如平头、悬针)和纳音交战,用于判断先天体质、有无夭折风险等。

    • 命宫:主要用于起“十二宫”(即“花園十二宫”),如命宫、夫妻宫、财帛宫等,用于多维度分析人生事项。

    • 神煞体系:是两大体系共用的重要部分。包括:

      • 马前神煞、太岁十二神。

      • 常用吉凶神煞:如红鸾、天喜、文昌、游奕、暗金煞、白衣、破碎、呻吟等。神煞需结合具体宫位和五行生克使用。

    • 虚中法看流年:核心是 “逐限而行”。将人生划分为不同年限(如年柱管1-16岁),重点看所行大运或流年 那一柱的天干地支,与年柱的禄命身产生何种生克合化及刑冲破害,并结合神煞,来判断该时段的吉凶。

    • 子平法论格局:核心是 月令分金定格局(如正官格、七杀格等)。需辨别格局的真假、成败。无格或破格时,则看喜用神。老师指出,真成格者(真富贵)极少。

    • 身强身弱:明确指出,身强身弱首先看年柱(年干、年支、纳音),这是先天体质根基。日元强弱是后天表现。日元强,承载财官的能力才强。

三、学习路径与经典推荐

  1. 核心经典(打基础必读)

    • 《渊海子平》:子平法的核心框架。

    • 《五行精纪》:虚中法(禄命法)的核心框架。

    • 《三命通会》:集大成的综合性经典。

  2. 其他经典作为视角补充:如《神峰通考》(讲病药)、《穷通宝鉴》(讲调候)、《子平真诠》(讲格局)等,它们提供了特定视角,但非全面基础。

  3. 学习方法

    • 先建立清晰框架:在脑中牢固建立“虚中-年柱-先天”和“子平-日柱-后天”两大框架,以及神煞、刑冲等公共方法。

    • 带着框架去学习:有了扎实基础和框架后,再去广泛听取各家之言,才能有判断力,将他人观点纳入自己的体系,而非被误导。

    • 重视赋文:如《千里马》、《络绎赋》、《金玉赋》等,这些是古人将理论应用于实战的总结,基础扎实后才能看懂并运用。

  4. 对市面上乱象的批判

    • 强烈反对自称“独创”、“秘传”而不引经据典的理论,认为“凡是离开经典的,皆是无源之水”。

    • 指出很多民间传承或盲派技法,其根源也公开承认来自上述经典。

    • 提醒学生睁大眼睛,谨慎对待那些标新立异、脱离经典的教学。

四、总结与劝诫

  • 最后归纳:八字的核心框架就是 “虚中的禄命身+神煞”“子平的月令格局+神煞” 的结合。刑冲破害、十二长生、旺相休囚等是服务于这两个核心的分析工具。

  • 终极劝告:“命理学没有秘密。命理学的基础逻辑在经典,实务传承在民间。” 要求学生沉下心来,回归经典,打好基础,以此立身,不贬低他人,但要有独立判断。