【注意】最后更新于 April 20, 2023,文中内容可能已过时,请谨慎使用。
和 AI 对话一段时间,受到很大的启发。
在 AI 辅助下,日常开发,时间和项目管理,效率都有了明显的提升。相信 AI 将在生活中扮演更多角色,影响自己的行为习惯。
网上看到已经有大牛,用 AI 实现了无代码开发,从项目框架设计,功能开发和测试发布,都由 AI 一步步回答实现,例如 mygptreader 。
受此启发,在尝试开发过程中,尽量使用 AI 来完成,功能的设计和开发。
例如,使用 swift 开发一个 snippet 转换插件过程中,只需负责提需求,验收 AI 代码可用性,然后集成到脚本运行就好。
这样以来,任务重心偏向了需求挖掘,功能设计,代码验收上。做这些工作,更多体现在领导和管理上,如何扮演好新的角色至关重要。
emacs 拥有丰富的插件,在 org-AI
的加持下, tj3
项目管理,博客写作 ox-hugo
插件, plantuml
插件, 代码块
插件等,都能有效的提升生产力。经过这次 AI 浪潮洗礼,将 emacs 训练成高效能七个习惯的执行者的愿望,也许指日可待了。
使用 AI 制作 prompt snippets 提升 chatgpt 沟通
使用脚本收集流行的 prompt 库,批量转换 snippet, 例如:alfred snippet , emacs snippet 等。
通过这个简单脚本的开发,借助 AI 尝试无代码编程。在需求,设计,编码,调试实战中,工作中心偏设计管理,尽量在 emacs 中探索可提升产出的技术栈,学习积累新的开发习惯。
技术设计:采用 swift 语言, JSON
库解析 propmt 源数据转为目标 snippt 格式。
开发工具:借助 emacs 插件提升产出效率。例如:利用 org-swift
plantuml
快速设计,测试等。
分析数据模型
prompt 数据源样例
这段 json 片段来自微信机器人 chat-on-wechat 中的角色插件,插件中整理很多关于角色 prompt。
主要功能:例如在片段的角色的描述,在微信中和 AI 聊天时,只要输入 佛祖
即可。
制作 snippet 会用到 title , descan remark 字段。
1
2
3
4
5
6
7
8
9
10
| {
"title": "佛祖",
"description": "从现在开始你是佛祖,你会像佛祖一样说话。你精通佛法,熟练使用佛教用语,你擅长利用佛学和心理学的知识解决人们的困扰。你在每次对话结尾都会加上佛教的祝福。",
"descn": "从现在开始你是佛祖,你会像佛祖一样说话。你精通佛法,熟练使用佛教用语,你擅长利用佛学和心理学的知识解决人们的困扰。你在每次对话结尾都会加上佛教的祝福。",
"wrapper": "您好佛祖,我:\"%s\"",
"remark": "扮演佛祖排忧解惑",
"tags": [
"interesting"
]
},
|
snippet 目标结构样例: emacs snippet 格式
这段显示的 or-ai
的 snippet 结构展示,作为脚本的输出格式。
snippet 的 key 使用 prompt 名称的中文全拼缩写。
例如:将 佛祖
prompt 转为 snippet 效果:
1
2
3
4
5
6
7
8
9
10
| # -*- mode: snippet -*-
# name: 佛祖
# key: fz
# --
#+begin_ai markdown :max-tokens 250
${1:[SYS]: ${2:从现在开始你是佛祖,你会像佛祖一样说话。你精通佛法,熟练使用佛教用语,你擅长利用佛学和心理学的知识解决人们的困扰。你在每次对话结尾都会加上佛教的祝福。}
}[ME]: 您好佛祖,我:
$0
#+end_ai
|
emacs + AI 开发模式
在 org 中进行 swift 语言开发,主要用到一下插件:
org-ai
在 org 中 AI 实时对话
org-swift
,支持 swift 脚本 org-babel ,在 org 中轻松运行脚本,便于测试验收代码,类似 swift playgroud 。
采用字符串的形式,处理格式转换,然后写入目标文件保存到文件
- 用变量模拟 json 数据
- 采用多行字符串组装要转换的格式
- 使用 print 验证字符串结果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| var name = "miao"
var key = "mn"
var prompt = "猫娘"
let snippet = """
# -*- mode: snippet -*-
# name: \(name)
# key: \(key)
# --
#+begin_ai markdown :max-tokens 250
${1:[SYS]: ${2:\(prompt)}
}[ME]: $0
"""
print(snippet)
|
打印结果:
1
2
3
4
5
6
7
8
| # -*- mode: snippet -*-
# name: miao
# key: mn
# --
#+begin_ai markdown :max-tokens 250
${1:[SYS]: ${2:猫娘}
}[ME]: $0
|
获取中文全拼缩
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
| import Foundation
func PYFirst(string:String?, _ allFirst:Bool=false)->String{
var py="#"
if let s = string {
if s == "" {
return py
}
let str = CFStringCreateMutableCopy(nil, 0, s as CFString)
CFStringTransform(str, nil, kCFStringTransformToLatin, false)
CFStringTransform(str, nil, kCFStringTransformStripCombiningMarks, false)
py = ""
if allFirst {
for x in (str! as String).components(separatedBy:" ") {
py += PYFirst(string:x)
}
} else {
py = (str! as NSString).substring(to: 1).uppercased()
}
}
return py
}
//调用示例,返回#
var s :String?
//PYFirst(string:s)
s = "中华人民共和国@hi wor\r\nld."
//调用示例,返回ZHRMGHGW
let result = PYFirst(string:s,true)
//调用示例,返回Z
let result2 = PYFirst(string:s)
print("结果1: \(result) \n 结果2: \(result2)")
|
1
2
| 结果1: ZHRMGHGW
result2: Z
|
脚本的核心功能和运用
使用 JSONEncoder 解析本地的 json 文件,转为 model 对象。
目前支持三个工具的 snippet
alfred snippet
转为 json 文件集合,需要手动压缩成 .zip
,然后命名为 .alfredsnippets
如果安装无效,尝试以下方式安装
- 在alfred snippet 新建一个snippet 集合,然后导出为
alfredsnippets
包 - 再使用 zip 工具不解压缩的情况下,将生成的 json 导入到 包中。
- 双击包,成功导入到 alred snippet 中。
emacs-snippet
auto-gpt yaml模板
使用方法:python -m auto-gpt –settings-file role.yaml
生成chatfred 的aliases
安装方法:把chatfred的内容拷贝到chatfred 配置项中
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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
|
public static func toSnippets(json:String) -> String? {
// 使用 JSONEncoder 解析本地的json 文件,转为model 对象。
let url = URL(fileURLWithPath: json)
let data = try! Data(contentsOf: url)
let prompt = try! JSONDecoder().decode(Prompt.self, from: data)
prompt.roles.map { role in
// 保存为json 文件
var wrapper = role.wrapper
wrapper.replaceAll(matching: "\n.*$", with: "")
do {
// alfred -----
let jsonEncoder = JSONEncoder()
let alfred = SnippetModel(uid: UUID().uuidString,
name: role.title,
keyword: role.title.pinyin.lowercased(),
snippet: role.descn)
let alfredM = AlfredModel(alfredsnippet: alfred)
jsonEncoder.outputFormatting = .prettyPrinted
let resultData = try jsonEncoder.encode(alfredM)
let filename = alfred.name + " [\(alfred.uid)]"
let newfile = "/Users/boyer/Desktop/propmt/\(filename).json"
let url = URL(fileURLWithPath: newfile)
try resultData.write(to: url, options: .atomic)
// emacs-snippet ---把字符串保存为文件 ---
let snippet = """
# -*- mode: snippet -*-
# name: \(role.title)
# key: \(alfred.keyword)
# group: \(role.tags.first ?? "")
# --
#+begin_ai markdown :max-tokens 250
[SYS]: \(role.descn)
[ME]: \(wrapper)
$0
#+end_ai
"""
let snippetfile = ".doom.d/snippets/org-mode/ai/\(alfred.name)"
let emacsnippet = Path.home+snippetfile
try! emacsnippet.write(snippet)
//auto-gpt -----
//使用方法:python -m auto-gpt --settings-file role.yaml
let auto_gpt = """
ai_goals:
- \(role.remark)
ai_name: \(role.title)
ai_role: \(role.descn)
"""
let autofile = ".dotfiles/auto-gpt/roles/\(role.title).yaml"
let autogpt = Path.home+autofile
try! autogpt.write(auto_gpt)
//生成chatfred 的aliases
//使用方法:把chatfred的内容拷贝到chatfred 配置项中。
let alfred_aliases = role.title.pinyin.lowercased() + "=" + role.descn + ";\n"
let fred = "Desktop/chatfred.txt"
let chatfred = Path.home+fred
// try! chatfred.append(alfred_aliases)
let fileHandle = try FileHandle(forWritingTo: chatfred.url)
fileHandle.seekToEndOfFile()
if let data = alfred_aliases.data(using: .utf8) {
fileHandle.write(data)
}
fileHandle.closeFile()
} catch {
print("生成失败")
}
}
return "生成成功"
}
|
TODO ob-babel 导入第三库遇到的问题
问题1. org-mode 9.6.1 在使用 var 传递变量失败
在导入第三方库时,通过 ai 提供了几种方法,验证都无效
- 使用:var myLibrary=“Regex” 在swift 块中,import $myLibrary
- 使用:var loadpath ="" 源码路径,在 emacs-elisp 块中夹带 load-path 方式
- 在 swift 块中使用 load-file 的方式加载 swift 文件,然后使用库方法
三种方法在验证之后都是无效的。
1
2
| (setq load-path (cons includepath load-path))
(load-file (concat includepath "Regex.swift"))
|
1
2
3
4
5
6
7
8
9
| let myString = $myString // 将Org-mode代码块中的myString变量赋值给Swift变量
print("声明的变量:\(myString)")
let pattern = "T.*T"
let regex = try! Regex(pattern)
if regex.matches(myString) {
print("Regex matched!")
} else {
print("Regex didn't match.")
}
|
1
2
3
4
5
| <stdin>:1:16: error: cannot find '$myString' in scope
let myString = $myString // 将Org-mode代码块中的myString变量赋值给Swift变量
<stdin>:5:10: error: value of type 'Regex<AnyRegexOutput>' has no member 'matches'
if regex.matches(myString) {
~~~~~ ^~~~~~~
|
1
2
3
4
5
6
| import Foundation
var text = "test\n \"%s\""
print("kkkk==\(text)")
//text.removeLast(4)//replacingOccurrences(of: "\"%s\"", with: "")
text.replaceAll(matching: "%.*$", with: "")
print("jjjj==\(text)")
|
1
2
3
| <stdin>:5:6: error: value of type 'String' has no member 'replaceAll'
text.replaceAll(matching: "%.*$", with: "")
~~~~ ^~~~~~~~~~
|