deel-local-cli 1.0.2 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +381 -7
- package/README.md +407 -7
- package/bin/deel.js +266 -234
- package/package.json +4 -3
- package/src/agent/budget.js +167 -0
- package/src/agent/grade.js +207 -0
- package/src/agent/loop.js +778 -574
- package/src/agent/modes.js +109 -28
- package/src/agent/project.js +171 -0
- package/src/agent/session.js +131 -12
- package/src/backend/learn.js +46 -4
- package/src/commands.js +73 -0
- package/src/oneshot.js +390 -327
- package/src/repl.js +1074 -887
- package/src/safety/audit.js +3 -1
- package/src/tools/index.js +500 -107
- package/src/tools/jobs.js +670 -0
- package/src/tools/outline.js +331 -0
- package/src/tools/task.js +153 -0
- package/src/tools/verify.js +306 -0
- package/src/tools/webfetch.js +152 -16
- package/src/ui/inputbox.js +97 -5
- package/src/ui/screen.js +51 -3
- package/src/ui/status.js +69 -4
- package/src/ui/working.js +8 -1
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 상한을 **모델에 맞춰** 정한다.
|
|
3
|
+
*
|
|
4
|
+
* ── 왜 고정 숫자를 버렸나 ───────────────────────────────────────────────
|
|
5
|
+
*
|
|
6
|
+
* 전에는 전부 못 박혀 있었다. 걸음 24회, Read 2,000줄, Glob 200개,
|
|
7
|
+
* WebFetch 20,000자. 그런데 이 값들이 맞는 모델은 **하나도 없다.**
|
|
8
|
+
*
|
|
9
|
+
* 8k 짜리 로컬 모델에 20,000자를 부어 넣으면 그 한 번으로 창이 넘친다.
|
|
10
|
+
* 앞엣말을 잊은 채로 답하니, 사람 눈에는 "모델이 멍청해졌다" 로 보인다.
|
|
11
|
+
*
|
|
12
|
+
* 655k 짜리 모델은 24걸음 만에 끊긴다. 대시보드 하나를 만들려면 폴더를
|
|
13
|
+
* 잡고 파일 몇 개를 만들고 돌려 보고 고쳐야 하는데, 만들다 만 채로 끝난다.
|
|
14
|
+
* 여유가 96% 남아 있는데도 그렇다.
|
|
15
|
+
*
|
|
16
|
+
* 같은 숫자가 한쪽에선 너무 크고 다른 쪽에선 너무 작다. 그러면 그건 숫자를
|
|
17
|
+
* 잘못 고른 게 아니라 **고정한 것 자체가 틀린 것**이다.
|
|
18
|
+
*
|
|
19
|
+
* 그래서 전부 컨텍스트에서 뽑아 쓴다. 큰 모델에는 크게 주고 작은 모델에는
|
|
20
|
+
* 작게 준다. 사람이 `/ctx` 로 컨텍스트를 다시 재면 이 값들도 같이 따라온다.
|
|
21
|
+
*
|
|
22
|
+
* ── 걸음 수는 목표가 아니라 마지막 안전장치다 ──────────────────────────
|
|
23
|
+
*
|
|
24
|
+
* 헛도는 것은 걸음 수로 못 잡는다 — 그건 '잘 되고 있는 긴 작업' 과 '헛도는
|
|
25
|
+
* 작업' 을 구분 못 한다. 헛도는 것은 같은 자리를 되풀이하는지로 잡고
|
|
26
|
+
* (loop.js), 컨텍스트가 차면 접는다(compact.js). 여기 값은 그 둘이 다 놓쳤을
|
|
27
|
+
* 때 끝없이 도는 것을 막는 **마지막 울타리**다. 그러니 넉넉해도 된다.
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
// 컨텍스트 1k 당 몇 걸음을 줄까. 일의 성격마다 다르다 —
|
|
31
|
+
// '묻기' 는 설명 한 번이면 끝이고, '총괄' 은 여러 갈래를 끝까지 끌고 간다.
|
|
32
|
+
const 걸음규칙 = {
|
|
33
|
+
ask: { 배수: 0.25, 최소: 4, 최대: 12 },
|
|
34
|
+
plan: { 배수: 0.6, 최소: 8, 최대: 40 },
|
|
35
|
+
architect: { 배수: 0.7, 최소: 8, 최대: 48 },
|
|
36
|
+
auto: { 배수: 1.5, 최소: 16, 최대: 200 },
|
|
37
|
+
code: { 배수: 1.5, 최소: 16, 최대: 200 },
|
|
38
|
+
debug: { 배수: 2, 최소: 16, 최대: 250 },
|
|
39
|
+
orchestrator: { 배수: 3, 최소: 24, 최대: 400 },
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const 사이 = (v, 최소, 최대) => Math.max(최소, Math.min(최대, Math.round(v)));
|
|
43
|
+
|
|
44
|
+
/** 컨텍스트가 아직 안 잡혔을 때 쓰는 값. 못 알아냈다는 뜻이지 정답이 아니다. */
|
|
45
|
+
const 모를때 = 32768;
|
|
46
|
+
|
|
47
|
+
const k = (ctx) => (Number(ctx) > 0 ? Number(ctx) : 모를때) / 1024;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* 이 모드·이 모델에서 한 턴에 몇 걸음까지 돌까.
|
|
51
|
+
*
|
|
52
|
+
* @param {string} 모드id auto · code · plan …
|
|
53
|
+
* @param {number} ctx 모델 컨텍스트 길이(토큰)
|
|
54
|
+
*/
|
|
55
|
+
export function 걸음수(모드id, ctx) {
|
|
56
|
+
const r = 걸음규칙[모드id] ?? 걸음규칙.auto;
|
|
57
|
+
return 사이(k(ctx) * r.배수, r.최소, r.최대);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* 한 번에 읽을 파일 줄 수.
|
|
62
|
+
*
|
|
63
|
+
* 8k 모델에 2,000줄을 부어 넣으면 그 한 번으로 창이 넘친다. 넘치면 접히고,
|
|
64
|
+
* 접히면 앞엣말을 잊는다 — 그런데 화면에는 `2,000줄` 이라고만 떠서 사람은
|
|
65
|
+
* 잘 읽은 줄 안다.
|
|
66
|
+
*/
|
|
67
|
+
export function 읽을줄수(ctx) {
|
|
68
|
+
return 사이(k(ctx) * 12, 200, 4000);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/** Glob 이 돌려줄 파일 개수. 목록은 한 줄에 한 개라 줄 수와 성격이 같다. */
|
|
72
|
+
export function 찾을개수(ctx) {
|
|
73
|
+
return 사이(k(ctx) * 6, 50, 1000);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** Grep 이 돌려줄 줄 수. */
|
|
77
|
+
export function 찾을줄수(ctx) {
|
|
78
|
+
return 사이(k(ctx) * 8, 80, 1500);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Outline 이 돌려줄 줄 수.
|
|
83
|
+
*
|
|
84
|
+
* Grep 보다 넉넉히 준다. 뼈대 한 줄은 ` 42 fn 접어쓰기` 처럼 짧은데,
|
|
85
|
+
* 그 한 줄이 파일 하나를 통째로 안 읽어도 되게 해 준다 — 줄당 값이 제일 크다.
|
|
86
|
+
* 8k 에서 120줄이면 파일 열댓 개의 모양이 들어온다. 그 정도면 "어디를 고칠지"
|
|
87
|
+
* 는 정해진다.
|
|
88
|
+
*/
|
|
89
|
+
export function 뼈대줄수(ctx) {
|
|
90
|
+
return 사이(k(ctx) * 15, 120, 2500);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* WebFetch 가 한 번에 가져올 글자 수.
|
|
95
|
+
*
|
|
96
|
+
* 토큰이 아니라 **글자** 다. 영문 JSON 은 3.6자에 1토큰이지만 한글은 1자에
|
|
97
|
+
* 1토큰이라, 같은 글자 수라도 한글이 세 배 넘게 무겁다. 무거운 쪽에 맞춘다 —
|
|
98
|
+
* 넘쳐서 잊는 것보다 모자라서 한 번 더 부르는 편이 낫다.
|
|
99
|
+
*/
|
|
100
|
+
export function 웹글자수(ctx) {
|
|
101
|
+
return 사이(k(ctx) * 400, 4000, 120000);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* 하위 작업이 돌 걸음 수.
|
|
106
|
+
*
|
|
107
|
+
* 부모보다 적게 준다. 하위 작업은 '한 덩이' 를 맡는 것이지 전체를 맡는 게
|
|
108
|
+
* 아니다. 부모만큼 주면 하위가 부모 일을 통째로 다시 하려 들고, 그러면
|
|
109
|
+
* 창을 나눈 뜻이 없어진다. 대신 너무 적으면 맡긴 덩이도 못 끝내니
|
|
110
|
+
* 8걸음은 무슨 일이 있어도 준다.
|
|
111
|
+
*/
|
|
112
|
+
export function 하위걸음수(모드id, ctx) {
|
|
113
|
+
return Math.max(8, Math.round(걸음수(모드id, ctx) / 2));
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* 하위 작업이 부모에게 돌려줄 요약의 길이(글자).
|
|
118
|
+
*
|
|
119
|
+
* 이게 하위 작업의 **존재 이유**다. 하위가 파일 열 개를 읽고 만들어도 부모
|
|
120
|
+
* 창에 들어가는 것은 이만큼뿐이다. 그러니 부모 창에 맞춰야지, 하위가 한 일의
|
|
121
|
+
* 양에 맞추면 안 된다 — 그러면 나눈 것이 도로 합쳐진다.
|
|
122
|
+
*
|
|
123
|
+
* 부모 창의 약 5% 를 넘지 않게 잡는다. 8k 면 400자, 655k 면 4,000자다.
|
|
124
|
+
*/
|
|
125
|
+
export function 요약길이(ctx) {
|
|
126
|
+
return 사이(k(ctx) * 50, 400, 4000);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* 도구 설명을 몇 글자까지 실을까.
|
|
131
|
+
*
|
|
132
|
+
* ── 이게 왜 필요한가 ─────────────────────────────────────────────────
|
|
133
|
+
*
|
|
134
|
+
* 도구 정의는 **매 요청에 통째로 다시 나간다.** 접기로는 못 줄이는 몫이다.
|
|
135
|
+
* 도구가 14종이 되면서 코드 모드 기준 2,058 → 2,354토큰이 됐고, 시스템
|
|
136
|
+
* 프롬프트까지 합치면 4,045토큰이다. 8k 모델이면 대화 한 줄 전에 **절반**이다.
|
|
137
|
+
*
|
|
138
|
+
* 그렇다고 도구를 뺄 수는 없다. 빼면 작은 모델만 할 수 있는 일이 달라져서,
|
|
139
|
+
* "환경마다 다르게 동작" 하게 된다 — 사용자가 피하려는 바로 그것이다.
|
|
140
|
+
* 그래서 **도구는 다 주고 설명만 줄인다.** 이름과 인자는 그대로 두므로
|
|
141
|
+
* 할 수 있는 일은 똑같고, 없어지는 것은 '왜 이걸 쓰는지' 하는 설득뿐이다.
|
|
142
|
+
*
|
|
143
|
+
* 큰 창에서는 안 줄인다(Infinity). 그 설득이 실제로 값을 하기 때문이다 —
|
|
144
|
+
* 모델이 Outline 을 Read 앞에 부르게 만드는 것은 그 두 문장이다.
|
|
145
|
+
*/
|
|
146
|
+
export function 설명길이(ctx) {
|
|
147
|
+
const n = Number(ctx) > 0 ? Number(ctx) : 모를때;
|
|
148
|
+
if (n >= 64000) return Infinity; // 자리가 넉넉하다. 그대로 준다
|
|
149
|
+
if (n >= 24000) return 220;
|
|
150
|
+
if (n >= 12000) return 140;
|
|
151
|
+
return 90; // 8k 언저리. 첫 문장 하나만 남는다
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/** `/ctx` 에서 지금 값이 얼마인지 보여 주려고 한데 모아 준다. */
|
|
155
|
+
export function 지금값(ctx, 모드id = 'auto') {
|
|
156
|
+
return {
|
|
157
|
+
걸음: 걸음수(모드id, ctx),
|
|
158
|
+
하위걸음: 하위걸음수(모드id, ctx),
|
|
159
|
+
읽기: 읽을줄수(ctx),
|
|
160
|
+
찾기: 찾을개수(ctx),
|
|
161
|
+
훑기: 찾을줄수(ctx),
|
|
162
|
+
뼈대: 뼈대줄수(ctx),
|
|
163
|
+
웹: 웹글자수(ctx),
|
|
164
|
+
도구설명: 설명길이(ctx),
|
|
165
|
+
요약: 요약길이(ctx),
|
|
166
|
+
};
|
|
167
|
+
}
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 모델 급 — 지금 붙어 있는 모델이 얼마나 하는가.
|
|
3
|
+
*
|
|
4
|
+
* ── budget.js 와 무엇이 다른가 ─────────────────────────────────────────
|
|
5
|
+
*
|
|
6
|
+
* budget.js 는 **창 크기**에서 값을 뽑는다. 얼마나 담을 수 있나 — 자리의 문제다.
|
|
7
|
+
* 여기는 **능력**을 본다. 얼마나 알아서 하나 — 사람으로 치면 손이 얼마나 가나.
|
|
8
|
+
*
|
|
9
|
+
* 둘은 같이 안 간다. 창이 128k 인 3B 모델이 있고, 창이 32k 인 아주 좋은 모델도
|
|
10
|
+
* 있다. 그래서 축을 갈라야 한다. 갈라 놓지 않으면 이런 일이 난다 —
|
|
11
|
+
*
|
|
12
|
+
* 창이 크다 → 프롬프트를 길게 써도 된다 → 긴 프롬프트를 준다
|
|
13
|
+
* 그런데 그 모델이 작다 → 긴 프롬프트를 못 따라간다 → 더 나빠진다
|
|
14
|
+
*
|
|
15
|
+
* ── 무엇을 보고 정하나 ─────────────────────────────────────────────────
|
|
16
|
+
*
|
|
17
|
+
* 이름에 든 파라미터 수(7b·70b)는 **짐작**이다. 로컬에서는 거의 언제나 이름에
|
|
18
|
+
* 들어 있어서 쓸모가 있지만, 사내 게이트웨이는 `gpt-oss` 처럼 아무것도 안 알려
|
|
19
|
+
* 준다. 그래서 이름만으로 정하지 않는다.
|
|
20
|
+
*
|
|
21
|
+
* 진짜 근거는 **이번 대화에서 실제로 본 것**이다.
|
|
22
|
+
* · 도구 인자(JSON)가 중간에 잘렸나 — 큰 모델은 거의 안 잘린다
|
|
23
|
+
* · Edit 의 old_string 이 파일과 안 맞았나 — 정확히 옮겨 적는 능력
|
|
24
|
+
* · 빈 답을 냈나 — 도구를 부르지도, 말을 하지도 않은 걸음
|
|
25
|
+
* · 같은 자리를 되풀이했나 — 제 상태를 못 좇는 것
|
|
26
|
+
*
|
|
27
|
+
* 이 넷은 전부 loop.js 가 이미 겪는 것들이다. 세어서 여기 알려 주면, 이 급은
|
|
28
|
+
* 대화가 길어질수록 정확해진다. 처음 한두 걸음은 이름으로 짐작하고, 그 뒤로는
|
|
29
|
+
* 실제로 본 것이 이긴다.
|
|
30
|
+
*
|
|
31
|
+
* ── 이 값이 무엇을 바꾸나 ──────────────────────────────────────────────
|
|
32
|
+
*
|
|
33
|
+
* 안전은 **안 바꾼다.** 작업 범위·승인·되돌리기·감사기록은 모든 급에서 같다.
|
|
34
|
+
* 바꾸는 것은 '얼마나 붙들어 주나' 뿐이다.
|
|
35
|
+
*
|
|
36
|
+
* 작은 급 한 번에 한 걸음씩. 절차를 번호로 못 박아 준다. 나눠 쓰기를 시킨다.
|
|
37
|
+
* 한 번에 만들 파일 수를 줄인다. 확인을 더 자주 시킨다.
|
|
38
|
+
* 큰 급 맡긴다. 절차 대신 목표를 준다. 한 번에 여러 개를 하게 둔다.
|
|
39
|
+
*
|
|
40
|
+
* 이게 "작은 모델도 쓸 만하게, 좋은 모델은 좋은 만큼" 이다.
|
|
41
|
+
*/
|
|
42
|
+
|
|
43
|
+
/** 급 이름. 숫자가 아니라 이름으로 쓰는 이유는 화면에 그대로 나가기 때문이다. */
|
|
44
|
+
export const 급들 = ['작음', '보통', '큼'];
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* 이름에서 파라미터 수를 읽어 본다.
|
|
48
|
+
*
|
|
49
|
+
* `qwen2.5-coder-32b-instruct-q4_k_m` 같은 이름에서 32 를 뽑는다.
|
|
50
|
+
* 못 읽으면 null 이다 — 모른다는 뜻이지 작다는 뜻이 아니다.
|
|
51
|
+
*
|
|
52
|
+
* 양자화 표시(q4_k_m·f16)와 판 번호(2.5)는 걸러야 한다. 안 그러면
|
|
53
|
+
* `qwen2.5` 의 2.5 를 2.5B 로 읽는다.
|
|
54
|
+
*/
|
|
55
|
+
export function 이름에서크기(모델이름) {
|
|
56
|
+
const s = String(모델이름 ?? '').toLowerCase();
|
|
57
|
+
// 앞뒤가 글자·숫자가 아닌 자리에서만 본다. 'q4' 나 'v3' 는 안 잡힌다.
|
|
58
|
+
const 후보 = [...s.matchAll(/(?:^|[^a-z0-9.])(\d{1,4}(?:\.\d)?)\s*b(?![a-z0-9])/g)]
|
|
59
|
+
.map((m) => Number(m[1]))
|
|
60
|
+
.filter((n) => n >= 0.5 && n <= 2000);
|
|
61
|
+
if (!후보.length) return null;
|
|
62
|
+
// 여러 개면 큰 쪽. moe 모델은 `a3b-30b` 처럼 활성/전체가 같이 적힌다.
|
|
63
|
+
return Math.max(...후보);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* 이름만 보고 짐작한 급. 실제로 본 것이 없을 때만 쓰는 첫 어림이다.
|
|
68
|
+
*
|
|
69
|
+
* 이름에서 아무것도 못 읽으면 '보통' 이다. 사내 게이트웨이가 그렇고,
|
|
70
|
+
* 그 자리에 붙는 모델은 대개 크다 — 작다고 잡으면 좋은 모델을 붙들어 맨다.
|
|
71
|
+
*/
|
|
72
|
+
export function 이름으로짐작(모델이름) {
|
|
73
|
+
const b = 이름에서크기(모델이름);
|
|
74
|
+
if (b == null) return { 급: '보통', 왜: '이름으로는 크기를 알 수 없습니다', 짐작: true };
|
|
75
|
+
if (b < 9) return { 급: '작음', 왜: `이름에 ${b}B 라고 적혀 있습니다`, 짐작: true };
|
|
76
|
+
if (b < 40) return { 급: '보통', 왜: `이름에 ${b}B 라고 적혀 있습니다`, 짐작: true };
|
|
77
|
+
return { 급: '큼', 왜: `이름에 ${b}B 라고 적혀 있습니다`, 짐작: true };
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* 이번 대화에서 실제로 본 것들을 세는 자.
|
|
82
|
+
*
|
|
83
|
+
* loop.js 가 겪는 대로 알려 주면 된다. 여기서는 세기만 하고, 판단은
|
|
84
|
+
* 아래 매김() 이 한다 — 세는 곳과 판단하는 곳을 갈라 놔야 검사가 쉽다.
|
|
85
|
+
*/
|
|
86
|
+
export class 지켜본것 {
|
|
87
|
+
constructor() {
|
|
88
|
+
this.걸음 = 0; // 모델을 부른 횟수
|
|
89
|
+
this.잘린인자 = 0; // 도구 인자(JSON)가 중간에서 끊긴 횟수
|
|
90
|
+
this.빈답 = 0; // 글도 도구도 없는 답
|
|
91
|
+
this.편집실패 = 0; // Edit 의 old_string 이 파일과 안 맞음
|
|
92
|
+
this.되풀이 = 0; // 같은 자리를 또 부름
|
|
93
|
+
this.도구성공 = 0; // 도구가 탈 없이 끝난 횟수
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
걸음셈() { this.걸음++; return this; }
|
|
97
|
+
본것(무엇) {
|
|
98
|
+
if (무엇 in this) this[무엇]++;
|
|
99
|
+
return this;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/** 걸음당 사고 비율. 걸음이 적으면 아직 판단하지 않는다. */
|
|
103
|
+
사고율() {
|
|
104
|
+
if (this.걸음 < 3) return null;
|
|
105
|
+
const 사고 = this.잘린인자 * 2 + this.빈답 * 2 + this.편집실패 + this.되풀이;
|
|
106
|
+
return 사고 / this.걸음;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* 급을 매긴다.
|
|
112
|
+
*
|
|
113
|
+
* 실제로 본 것이 있으면 그것이 이름보다 세다. "이름에 70B 라고 적혀 있는데
|
|
114
|
+
* 걸음마다 인자가 잘린다" 면 그건 70B 든 아니든 붙들어 줘야 하는 상태다.
|
|
115
|
+
*
|
|
116
|
+
* @param {object} conn 지금 연결 (model·ctx·maxOut)
|
|
117
|
+
* @param {지켜본것} 본것 이번 대화에서 겪은 것 (없어도 된다)
|
|
118
|
+
* @param {string} 사람이정한 '작음'|'보통'|'큼' — 사람이 정했으면 그게 답이다
|
|
119
|
+
*/
|
|
120
|
+
export function 매김(conn, 본것 = null, 사람이정한 = null) {
|
|
121
|
+
if (급들.includes(사람이정한)) {
|
|
122
|
+
return { 급: 사람이정한, 왜: '사용자가 직접 정했습니다', 짐작: false };
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const 첫어림 = 이름으로짐작(conn?.model);
|
|
126
|
+
const 율 = 본것?.사고율?.() ?? null;
|
|
127
|
+
if (율 == null) return 첫어림;
|
|
128
|
+
|
|
129
|
+
/*
|
|
130
|
+
* 실제로 본 것으로 고쳐 잡는다.
|
|
131
|
+
*
|
|
132
|
+
* 숫자의 뜻: 걸음 하나마다 인자 잘림이나 빈 답이 한 번씩 나면 율이 2 다.
|
|
133
|
+
* 그 상태로는 무엇을 맡겨도 안 끝난다 — 무조건 '작음' 으로 내린다.
|
|
134
|
+
* 반대로 열 걸음을 사고 없이 돌면 율이 0 이고, 그러면 이름이 뭐라 하든
|
|
135
|
+
* 한 단 올린다. 그 모델은 실제로 잘하고 있다.
|
|
136
|
+
*/
|
|
137
|
+
const 자리 = 급들.indexOf(첫어림.급);
|
|
138
|
+
if (율 >= 0.8) {
|
|
139
|
+
return { 급: '작음', 왜: `${본것.걸음}걸음 도는 동안 사고가 잦았습니다 (인자 잘림 ${본것.잘린인자} · 빈 답 ${본것.빈답} · 편집 실패 ${본것.편집실패})`, 짐작: false };
|
|
140
|
+
}
|
|
141
|
+
if (율 >= 0.3 && 자리 > 0) {
|
|
142
|
+
return { 급: 급들[자리 - 1], 왜: `${본것.걸음}걸음 중 몇 번 어긋났습니다 — 한 단 낮춰 잡습니다`, 짐작: false };
|
|
143
|
+
}
|
|
144
|
+
if (율 === 0 && 본것.걸음 >= 8 && 자리 < 급들.length - 1) {
|
|
145
|
+
return { 급: 급들[자리 + 1], 왜: `${본것.걸음}걸음을 사고 없이 돌았습니다 — 한 단 올려 잡습니다`, 짐작: false };
|
|
146
|
+
}
|
|
147
|
+
return { ...첫어림, 짐작: false, 왜: `${첫어림.왜} · ${본것.걸음}걸음 지켜본 결과도 그대로입니다` };
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* 급마다 달라지는 손잡이들.
|
|
152
|
+
*
|
|
153
|
+
* 여기 있는 것은 전부 **얼마나 붙들어 주나** 다. 안전에 닿는 것은 하나도 없다.
|
|
154
|
+
*/
|
|
155
|
+
const 손잡이 = {
|
|
156
|
+
작음: {
|
|
157
|
+
한번에쓸파일: 3, // 한 Write 로 만들 파일 수. 많으면 인자가 잘린다
|
|
158
|
+
한번에읽을파일: 2, // 한 걸음에 묶어 읽을 파일 수
|
|
159
|
+
나눠쓰기줄: 200, // 이보다 길면 Write+Append 로 나누라고 이른다
|
|
160
|
+
절차를못박나: true, // 프롬프트에 번호 매긴 순서를 준다
|
|
161
|
+
확인을시키나: true, // 단계마다 Verify 를 시킨다
|
|
162
|
+
하위작업권함: false, // 하위 작업까지 시키면 갈피를 잃는다
|
|
163
|
+
},
|
|
164
|
+
보통: {
|
|
165
|
+
한번에쓸파일: 6,
|
|
166
|
+
한번에읽을파일: 4,
|
|
167
|
+
나눠쓰기줄: 400,
|
|
168
|
+
절차를못박나: true,
|
|
169
|
+
확인을시키나: true,
|
|
170
|
+
하위작업권함: true,
|
|
171
|
+
},
|
|
172
|
+
큼: {
|
|
173
|
+
한번에쓸파일: 12,
|
|
174
|
+
한번에읽을파일: 8,
|
|
175
|
+
나눠쓰기줄: 800,
|
|
176
|
+
절차를못박나: false, // 목표만 주면 알아서 한다. 절차는 오히려 방해다
|
|
177
|
+
확인을시키나: true, // 이건 급과 상관없다 — 확인은 언제나 시킨다
|
|
178
|
+
하위작업권함: true,
|
|
179
|
+
},
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
/** 이 급에서 쓸 값들. */
|
|
183
|
+
export function 값(급) {
|
|
184
|
+
return 손잡이[급] ?? 손잡이.보통;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* 프롬프트에 붙일 한 문단.
|
|
189
|
+
*
|
|
190
|
+
* 작은 모델에는 **짧고 못 박은** 글을 준다. 길게 쓰면 안 된다 — 창도 좁고,
|
|
191
|
+
* 긴 글을 끝까지 따라가는 것 자체가 이 급이 잘 못하는 일이다.
|
|
192
|
+
* 큰 모델에는 아예 안 붙인다. 붙이면 이미 아는 것을 다시 읽느라 자리만 먹는다.
|
|
193
|
+
*/
|
|
194
|
+
export function 급말(급) {
|
|
195
|
+
const v = 값(급);
|
|
196
|
+
if (급 === '큼') return '';
|
|
197
|
+
const 줄 = [];
|
|
198
|
+
줄.push('이 모델에 맞춘 것:');
|
|
199
|
+
줄.push(`- 파일을 한 번에 만들 때는 ${v.한번에쓸파일}개까지만. 더 있으면 나눠서 여러 번 불러라.`);
|
|
200
|
+
줄.push(`- ${v.나눠쓰기줄}줄이 넘는 파일은 Write 로 앞부분만 만들고 Append 로 이어 붙여라.`);
|
|
201
|
+
if (급 === '작음') {
|
|
202
|
+
줄.push('- 한 걸음에 한 가지만 해라. 여러 도구를 한꺼번에 부르지 마라.');
|
|
203
|
+
줄.push('- 고칠 파일은 Read 로 읽은 **바로 다음 걸음**에 고쳐라. 사이에 다른 일을 넣지 마라.');
|
|
204
|
+
}
|
|
205
|
+
줄.push('- 끝맺기 전에 Verify 를 불러라. 탈이 나오면 고치고 다시 불러라.');
|
|
206
|
+
return 줄.join('\n');
|
|
207
|
+
}
|