nblog_zon 0.0.77 → 0.0.79
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.
- checksums.yaml +4 -4
- data/lib/nblog_zon.rb +165 -85
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 90f5b5abe540ae0b9c9aa6fe9ff2d0dd4995853214960b6891368585b3d7de90
|
4
|
+
data.tar.gz: b8ece68d61b394efa5dd1ba090dd1abd77c3fc46ebed845f7812a26543a5b614
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 10d0b9dd93709d013ecbb02c04a392336f9ee36d7218fae8fd1c5133f29d50a69eeaae29d172e428ae0b3698ea7e0a267a089346d63658ce98e1bac841be83c6
|
7
|
+
data.tar.gz: e715db872cc696a71cc70374bbe7916bd9359e4ec2b4aac7713fc27284075792cb596318b0a49b2099bf6d28716a2173e6cf77d258785c8da81170b32fb09796
|
data/lib/nblog_zon.rb
CHANGED
@@ -22,93 +22,107 @@ using Rainbow
|
|
22
22
|
include Glimmer
|
23
23
|
|
24
24
|
class Chat
|
25
|
-
def initialize(api_key)
|
25
|
+
def initialize(api_key, gpt_keyword_prompt)
|
26
26
|
@api_key = api_key
|
27
|
+
@gpt_keyword_prompt = gpt_keyword_prompt
|
27
28
|
end
|
28
29
|
|
29
|
-
def
|
30
|
-
|
31
|
-
h = {
|
32
|
-
'Content-Type' => 'application/json',
|
33
|
-
'Authorization' => 'Bearer ' + @api_key
|
34
|
-
}
|
35
|
-
d = {
|
36
|
-
#'model' => 'gpt-3.5-turbo',
|
37
|
-
'model' => 'gpt-4',
|
38
|
-
'messages' => [{
|
39
|
-
"role" => "assistant",
|
40
|
-
"content" => keyword.to_s+" 소개하는 글을 1500자에서 2500자 사이로 만들어줘"
|
41
|
-
}]
|
42
|
-
}
|
43
|
-
answer = ''
|
44
|
-
begin
|
45
|
-
req = HTTP.headers(h).post(url, :json => d)
|
46
|
-
print(req.to_s)
|
47
|
-
answer = JSON.parse(req.to_s)['choices'][0]['message']['content']
|
48
|
-
rescue => e
|
49
|
-
begin
|
50
|
-
answer = JSON.parse(req.to_s)['choices'][0]['message']['message']
|
51
|
-
rescue
|
30
|
+
def message(keyword)
|
31
|
+
puts 'Sending request to GPT...(키워드 기반 글 생성 중...)'
|
52
32
|
|
33
|
+
# "키워드 기반 글 생성 중..." 메시지 출력 스레드
|
34
|
+
thread = Thread.new do
|
35
|
+
while true
|
36
|
+
print "▶"
|
37
|
+
sleep 3
|
53
38
|
end
|
54
39
|
end
|
55
40
|
|
56
|
-
|
57
|
-
print('api return ==> ')
|
58
|
-
puts(answer)
|
59
|
-
|
60
|
-
return answer
|
61
|
-
end
|
62
|
-
|
63
|
-
def message(keyword)
|
64
|
-
puts 'chat gpt ...'
|
65
41
|
url = 'https://api.openai.com/v1/chat/completions'
|
66
|
-
|
42
|
+
headers = {
|
67
43
|
'Content-Type' => 'application/json',
|
68
44
|
'Authorization' => 'Bearer ' + @api_key
|
69
45
|
}
|
70
|
-
|
71
|
-
|
46
|
+
|
47
|
+
# 사용자로부터 받은 입력과 GPT 프롬프트의 토큰 수 계산
|
48
|
+
message_tokens = calculate_tokens(keyword) + calculate_tokens(@gpt_keyword_prompt)
|
49
|
+
|
50
|
+
# 8,192 토큰을 초과하지 않도록 최대 토큰 수를 설정
|
51
|
+
max_response_tokens = [8192 - message_tokens, 4000].min # 8,192 - 입력된 토큰 수, 4,000 이하로 설정
|
52
|
+
|
53
|
+
# 요청 데이터 설정
|
54
|
+
data = {
|
72
55
|
'model' => 'gpt-4',
|
73
|
-
'messages' => [
|
74
|
-
|
75
|
-
|
76
|
-
|
56
|
+
'messages' => [
|
57
|
+
{
|
58
|
+
"role" => "assistant",
|
59
|
+
"content" => "#{keyword}\n#{@gpt_keyword_prompt}"
|
60
|
+
}
|
61
|
+
],
|
62
|
+
'max_tokens' => max_response_tokens # 최대 응답 토큰 설정
|
77
63
|
}
|
64
|
+
|
65
|
+
|
66
|
+
|
78
67
|
answer = ''
|
79
68
|
begin
|
80
|
-
req = HTTP.headers(
|
81
|
-
print(req.to_s)
|
82
|
-
answer = JSON.parse(req.to_s)['choices'][0]['message']['content']
|
83
|
-
rescue => e
|
84
|
-
begin
|
85
|
-
answer = JSON.parse(req.to_s)['choices'][0]['message']['message']
|
86
|
-
rescue
|
69
|
+
req = HTTP.headers(headers).post(url, :json => data)
|
87
70
|
|
71
|
+
# 상태 코드 확인
|
72
|
+
if req.status != 200
|
73
|
+
raise "HTTP Error: #{req.status}, Response Body: #{req.body.to_s}"
|
88
74
|
end
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
75
|
+
|
76
|
+
# 응답 내용 출력 (디버깅용)
|
77
|
+
response = JSON.parse(req.to_s)
|
78
|
+
|
79
|
+
|
80
|
+
# 응답 데이터에서 안전하게 값 추출
|
81
|
+
if response['choices'] && response['choices'][0] && response['choices'][0]['message']
|
82
|
+
answer = response['choices'][0]['message']['content']
|
83
|
+
else
|
84
|
+
raise "Invalid API response format"
|
95
85
|
end
|
96
|
-
|
86
|
+
rescue => e
|
87
|
+
# 오류 메시지 출력
|
88
|
+
puts "Error occurred: #{e.message}"
|
89
|
+
answer = "오류가 발생했습니다."
|
97
90
|
end
|
98
91
|
|
99
|
-
|
100
|
-
|
92
|
+
# "생성 중..." 메시지 출력 종료
|
93
|
+
thread.kill
|
101
94
|
|
95
|
+
# 결과 로그 출력
|
96
|
+
puts "Final API response ==> #{answer}"
|
102
97
|
return answer
|
103
98
|
end
|
99
|
+
|
100
|
+
def calculate_tokens(text)
|
101
|
+
# 간단한 방식으로 텍스트의 토큰 수 계산 (정확도는 다를 수 있음)
|
102
|
+
# OpenAI API는 1토큰이 대략 4글자 정도임
|
103
|
+
text.split(/\s+/).length # 간단한 단어 수로 계산
|
104
|
+
end
|
104
105
|
end
|
105
106
|
|
107
|
+
|
108
|
+
|
109
|
+
|
110
|
+
|
106
111
|
class Chat_title
|
107
|
-
def initialize(api_key)
|
112
|
+
def initialize(api_key, gpt_title_prompt)
|
108
113
|
@api_key = api_key
|
114
|
+
@gpt_title_prompt = gpt_title_prompt
|
109
115
|
end
|
110
116
|
|
111
117
|
def message(title)
|
118
|
+
puts 'Sending request to GPT...(제목 생성 중...)'
|
119
|
+
# "키워드 기반 글 생성 중..." 메시지를 별도 스레드로 처리
|
120
|
+
thread = Thread.new do
|
121
|
+
while true
|
122
|
+
print "▶"
|
123
|
+
sleep(3)
|
124
|
+
end
|
125
|
+
end
|
112
126
|
url = 'https://api.openai.com/v1/chat/completions'
|
113
127
|
headers = {
|
114
128
|
'Content-Type' => 'application/json',
|
@@ -122,15 +136,15 @@ class Chat_title
|
|
122
136
|
},
|
123
137
|
{
|
124
138
|
"role" => "user",
|
125
|
-
"content" => "#{
|
139
|
+
"content" => "#{@gpt_title_prompt}\n#{title}"
|
126
140
|
}]
|
127
141
|
}
|
128
142
|
|
129
143
|
begin
|
130
144
|
req = HTTP.headers(headers).post(url, json: data)
|
131
|
-
|
145
|
+
|
132
146
|
response = JSON.parse(req.body.to_s)
|
133
|
-
|
147
|
+
|
134
148
|
|
135
149
|
if req.status == 429
|
136
150
|
return "API 요청 제한을 초과했습니다. 플랜 및 할당량을 확인하세요."
|
@@ -138,11 +152,18 @@ class Chat_title
|
|
138
152
|
|
139
153
|
# 응답 데이터에서 안전하게 값 추출
|
140
154
|
answer = response.dig('choices', 0, 'message', 'content')
|
141
|
-
|
155
|
+
|
156
|
+
# 따옴표 제거
|
157
|
+
answer = answer.gsub('"', '') if answer
|
158
|
+
|
159
|
+
answer ||= title # 응답이 없을 경우 기본 메시지 설정
|
142
160
|
rescue => e
|
143
161
|
puts "Error: #{e.message}"
|
144
162
|
answer = "오류가 발생했습니다."
|
145
163
|
end
|
164
|
+
|
165
|
+
# "생성 중..." 메시지 출력 종료
|
166
|
+
thread.kill
|
146
167
|
|
147
168
|
puts 'API return ==> '
|
148
169
|
puts answer
|
@@ -150,12 +171,23 @@ class Chat_title
|
|
150
171
|
end
|
151
172
|
end
|
152
173
|
|
174
|
+
|
153
175
|
class Chat_content
|
154
|
-
def initialize(api_key)
|
176
|
+
def initialize(api_key, gpt_content_prompt)
|
155
177
|
@api_key = api_key
|
178
|
+
@gpt_content_prompt = gpt_content_prompt
|
156
179
|
end
|
157
180
|
|
158
181
|
def message(content)
|
182
|
+
puts 'Sending request to GPT...(내용 변형 중...)'
|
183
|
+
puts '주의:GPT 특성상 원고 길이가 공백 포함 4천자를 넘기면 오류가 발생할 수 있습니다.'
|
184
|
+
# "키워드 기반 글 생성 중..." 메시지를 별도 스레드로 처리
|
185
|
+
thread = Thread.new do
|
186
|
+
while true
|
187
|
+
print "▶"
|
188
|
+
sleep(3)
|
189
|
+
end
|
190
|
+
end
|
159
191
|
|
160
192
|
url = 'https://api.openai.com/v1/chat/completions'
|
161
193
|
headers = {
|
@@ -170,15 +202,16 @@ class Chat_content
|
|
170
202
|
},
|
171
203
|
{
|
172
204
|
"role" => "user",
|
173
|
-
"content" => "#{content}
|
205
|
+
"content" => "#{@gpt_content_prompt}\n#{content}"
|
206
|
+
|
174
207
|
}]
|
175
208
|
}
|
176
209
|
|
177
210
|
begin
|
178
211
|
req = HTTP.headers(headers).post(url, json: data)
|
179
|
-
|
212
|
+
|
180
213
|
response = JSON.parse(req.body.to_s)
|
181
|
-
|
214
|
+
|
182
215
|
|
183
216
|
if req.status == 429
|
184
217
|
return "API 요청 제한을 초과했습니다. 플랜 및 할당량을 확인하세요."
|
@@ -192,6 +225,9 @@ class Chat_content
|
|
192
225
|
answer = "오류가 발생했습니다."
|
193
226
|
end
|
194
227
|
|
228
|
+
# "생성 중..." 메시지 출력 종료
|
229
|
+
thread.kill
|
230
|
+
|
195
231
|
puts 'API return ==> '
|
196
232
|
puts answer
|
197
233
|
answer
|
@@ -199,6 +235,7 @@ class Chat_content
|
|
199
235
|
end
|
200
236
|
|
201
237
|
|
238
|
+
|
202
239
|
#############################################gpt############################################
|
203
240
|
|
204
241
|
class Naver
|
@@ -2393,10 +2430,19 @@ class Wordpress
|
|
2393
2430
|
end
|
2394
2431
|
|
2395
2432
|
if @data['포스트설정']['gpt제목'].checked?
|
2396
|
-
|
2433
|
+
gpt_title_prompt = @data['포스트설정']['gpt제목_프롬프트'].text.to_s.force_encoding('utf-8')
|
2434
|
+
|
2435
|
+
# 공백을 포함한 빈 문자열을 체크하기 위해 strip을 사용
|
2436
|
+
gpt_title_prompt_sample = gpt_title_prompt.strip.empty? ? "프롬프트: 문장을 비슷한 길이로 ChatGPT의 멘트는 빼고 표현을 더 추가해서 하나만 만들어줘." : gpt_title_prompt
|
2437
|
+
|
2438
|
+
# gpt_title_prompt_sample을 Chat_title 객체에 전달
|
2439
|
+
chat = Chat_title.new(@data['포스트설정']['api_key'].text.to_s.force_encoding('utf-8'), gpt_title_prompt_sample)
|
2440
|
+
|
2441
|
+
# 메시지 요청 후 title에 저장
|
2397
2442
|
gpt_text1 = chat.message(title)
|
2398
2443
|
title = gpt_text1.to_s
|
2399
2444
|
end
|
2445
|
+
|
2400
2446
|
|
2401
2447
|
|
2402
2448
|
@data['table'][index][-1] = 5
|
@@ -2439,18 +2485,16 @@ class Wordpress
|
|
2439
2485
|
|
2440
2486
|
|
2441
2487
|
if @data['포스트설정']['gpt내용'].checked?
|
2488
|
+
gpt_content_prompt = @data['포스트설정']['gpt내용_프롬프트'].text.to_s.force_encoding('utf-8')
|
2442
2489
|
api_key = @data['포스트설정']['api_key'].text.to_s.force_encoding('utf-8')
|
2443
|
-
#key_change = @data['포스트설정']['특정단어키워드로변경값'].text.to_s.force_encoding('utf-8')
|
2444
|
-
#imotcon_change = @data['포스트설정']['스티커로변경단어'].text.to_s.force_encoding('utf-8')
|
2445
|
-
#template_change = @data['포스트설정']['내템플릿변경단어'].text.to_s.force_encoding('utf-8')
|
2446
|
-
#ttdanar_change = @data['포스트설정']['단어링크적용단어'].text.to_s.force_encoding('utf-8')
|
2447
|
-
#sajine_change = @data['포스트설정']['단어사진으로변경단어'].text.to_s.force_encoding('utf-8')
|
2448
|
-
#mov_change = @data['포스트설정']['영상으로변경단어'].text.to_s.force_encoding('utf-8')
|
2449
|
-
#map_change = @data['포스트설정']['지도로변경단어'].text.to_s.force_encoding('utf-8')
|
2450
|
-
#inyong9_change = @data['포스트설정']['인용구변경단어'].text.to_s.force_encoding('utf-8')
|
2451
|
-
|
2452
2490
|
|
2453
|
-
|
2491
|
+
# 공백을 포함한 빈 문자열을 체크하기 위해 strip을 사용
|
2492
|
+
gpt_content_prompt_sample = gpt_content_prompt.strip.empty? ? "프롬프트:ChatGPT의 멘트는 빼고 위 전체적인 내용의 형식을 똑같이 표현을 더 추가하고 유사어로 변경하여 하나 만들어줘! 전화번호,연락처,가격,홈페이지안내 ,상담안내 관련 문구는 유지해야해" : gpt_content_prompt
|
2493
|
+
|
2494
|
+
# Chat_content 객체 생성 시 api_key와 gpt_content_prompt_sample을 두 개의 인자로 전달
|
2495
|
+
chat = Chat_content.new(api_key, gpt_content_prompt_sample)
|
2496
|
+
|
2497
|
+
# 메시지 요청 후 content에 저장
|
2454
2498
|
gpt_text3 = chat.message(content)
|
2455
2499
|
content = gpt_text3.to_s
|
2456
2500
|
end
|
@@ -2654,13 +2698,17 @@ class Wordpress
|
|
2654
2698
|
@data['table'] << []
|
2655
2699
|
@data['table'].pop
|
2656
2700
|
if @data['포스트설정']['gpt키워드'].checked?
|
2657
|
-
|
2701
|
+
gpt_keyword_prompt = @data['포스트설정']['gpt키워드_프롬프트'].text.to_s.force_encoding('utf-8')
|
2702
|
+
gpt_keyword_prompt_sample = gpt_keyword_prompt.strip.empty? ? "프롬프트: 관련된 글을 1500자에서 2500자 사이로 만들어줘" : gpt_keyword_prompt
|
2703
|
+
chat = Chat.new(@data['포스트설정']['api_key'].text.to_s.force_encoding('utf-8'), gpt_keyword_prompt)
|
2658
2704
|
gpt_text = chat.message(keyword)
|
2659
|
-
content = content.to_s + "\n(자동생성글)\n" + gpt_text.to_s
|
2705
|
+
#content = content.to_s + "\n(자동생성글)\n" + gpt_text.to_s
|
2706
|
+
content = content.to_s + "(자동생성글)" + gpt_text.to_s
|
2660
2707
|
elsif @data['포스트설정']['내용을자동생성'].checked?
|
2661
2708
|
content = auto_text
|
2662
2709
|
elsif @data['포스트설정']['내용과자동생성'].checked?
|
2663
|
-
content = content + "\n(자동생성글)\n" + auto_text
|
2710
|
+
#content = content + "\n(자동생성글)\n" + auto_text
|
2711
|
+
content = content + "(자동생성글)" + auto_text
|
2664
2712
|
end
|
2665
2713
|
|
2666
2714
|
if @data['포스트설정']['내용키워드삽입'].checked?
|
@@ -2695,7 +2743,8 @@ class Wordpress
|
|
2695
2743
|
end
|
2696
2744
|
|
2697
2745
|
if @data['포스트설정']['내용을자동생성'].checked?
|
2698
|
-
content2 = content.split("\n")
|
2746
|
+
#content2 = content.split("\n")
|
2747
|
+
content2 = content.split
|
2699
2748
|
end
|
2700
2749
|
|
2701
2750
|
if @data['포스트설정']['내용과자동생성'].checked? or @data['포스트설정']['gpt키워드'].checked?
|
@@ -4010,6 +4059,11 @@ class Wordpress
|
|
4010
4059
|
}
|
4011
4060
|
}
|
4012
4061
|
} }
|
4062
|
+
horizontal_box{
|
4063
|
+
stretchy false
|
4064
|
+
@data['포스트설정']['gpt키워드_프롬프트'] = entry(){
|
4065
|
+
text '프롬프트:관련 글을 1500자에서 2500자 사이로 만들어줘'
|
4066
|
+
}}
|
4013
4067
|
horizontal_box{
|
4014
4068
|
stretchy false
|
4015
4069
|
grid{
|
@@ -4126,6 +4180,11 @@ class Wordpress
|
|
4126
4180
|
|
4127
4181
|
|
4128
4182
|
}}}
|
4183
|
+
horizontal_box{
|
4184
|
+
stretchy false
|
4185
|
+
@data['포스트설정']['gpt제목_프롬프트'] = entry(){
|
4186
|
+
text '프롬프트:비슷한 길이로 제목으로 사용할수있게 하나만 만들어줘'
|
4187
|
+
}}
|
4129
4188
|
horizontal_box{
|
4130
4189
|
stretchy false
|
4131
4190
|
grid{
|
@@ -4239,6 +4298,11 @@ class Wordpress
|
|
4239
4298
|
|
4240
4299
|
|
4241
4300
|
}}}
|
4301
|
+
horizontal_box{
|
4302
|
+
stretchy false
|
4303
|
+
@data['포스트설정']['gpt내용_프롬프트'] = entry(){
|
4304
|
+
text '프롬프트:동의어,유사어를 이용해 변경해줘'
|
4305
|
+
}}
|
4242
4306
|
horizontal_box{
|
4243
4307
|
stretchy false
|
4244
4308
|
grid{
|
@@ -4848,7 +4912,7 @@ class Wordpress
|
|
4848
4912
|
left 1
|
4849
4913
|
text 'URL'
|
4850
4914
|
}
|
4851
|
-
@data['포스트설정']['내용을자동생성'] = checkbox('키워드기반
|
4915
|
+
@data['포스트설정']['내용을자동생성'] = checkbox('키워드기반 글만 등록(GPT사용시 체크 해제)'){
|
4852
4916
|
top 9
|
4853
4917
|
left 0
|
4854
4918
|
on_toggled{
|
@@ -4860,10 +4924,19 @@ class Wordpress
|
|
4860
4924
|
end
|
4861
4925
|
}
|
4862
4926
|
}
|
4863
|
-
|
4864
|
-
|
4927
|
+
label('※GPT사용시 내용설정 탭에서 설정'){
|
4928
|
+
top 9
|
4929
|
+
left 1
|
4930
|
+
}
|
4931
|
+
|
4932
|
+
label('※GPT 미 사용시 세팅 권장'){
|
4933
|
+
top 9
|
4934
|
+
left 3
|
4935
|
+
}
|
4936
|
+
|
4937
|
+
|
4865
4938
|
aa1 = 2
|
4866
|
-
@data['포스트설정']['내용과자동생성'] = checkbox('
|
4939
|
+
@data['포스트설정']['내용과자동생성'] = checkbox('원고+키워드기반 글 등록(GPT사용시 체크 해제)') {
|
4867
4940
|
top 10 + aa1
|
4868
4941
|
left 0
|
4869
4942
|
on_toggled {
|
@@ -4879,7 +4952,14 @@ class Wordpress
|
|
4879
4952
|
end
|
4880
4953
|
}
|
4881
4954
|
}
|
4882
|
-
|
4955
|
+
label('※GPT사용시 내용설정 탭에서 설정'){
|
4956
|
+
top 10 + aa1
|
4957
|
+
left 1
|
4958
|
+
}
|
4959
|
+
label('※GPT 미 사용시 세팅 권장'){
|
4960
|
+
top 10 + aa1
|
4961
|
+
left 3
|
4962
|
+
}
|
4883
4963
|
@data['포스트설정']['내용투명'] = checkbox('키워드 기반 자동 생성글 안보이게 처리') {
|
4884
4964
|
top 11 + aa1
|
4885
4965
|
left 0
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nblog_zon
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.79
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- zon
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-02-
|
11
|
+
date: 2025-02-13 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: File to Clipboard gem
|
14
14
|
email: rnjstnswp123@naver.com
|