File size: 16,327 Bytes
b4251f4
 
 
 
 
80f4b08
 
 
172a968
1ced91c
 
c4d4857
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1ced91c
 
 
 
 
 
 
 
 
 
 
0121f83
80f4b08
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b4251f4
 
 
0121f83
 
 
 
 
 
 
f83e3f8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1ced91c
0121f83
1ced91c
b4251f4
 
0121f83
b4251f4
 
 
 
 
 
 
0121f83
 
 
 
 
b4251f4
 
 
 
 
 
 
 
 
 
 
 
1ced91c
80f4b08
 
 
 
 
 
 
b4251f4
1ced91c
80f4b08
1ced91c
c4d4857
 
 
 
 
 
 
 
 
 
 
1ced91c
b4251f4
 
 
 
8697be1
 
 
77eed2b
b4251f4
8697be1
 
 
77eed2b
8697be1
 
 
 
77eed2b
 
80f4b08
77eed2b
80f4b08
77eed2b
 
 
 
 
 
b4251f4
0121f83
b4251f4
6887924
 
 
b4251f4
1ced91c
 
 
 
 
 
b4251f4
1ced91c
 
b4251f4
 
 
 
6887924
b4251f4
 
 
0121f83
b4251f4
 
 
0121f83
b4251f4
 
 
0121f83
b4251f4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
80f4b08
 
b4251f4
 
 
8697be1
 
 
80f4b08
77eed2b
b4251f4
 
0121f83
1ced91c
b4251f4
0121f83
 
1ced91c
 
b4251f4
 
 
 
 
 
0121f83
1ced91c
 
b4251f4
 
 
 
 
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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
## chatGPT with Gradio 起手式
## 在你的資料夾新增 .env 檔案,並在裡面寫入 API_KEY=你的API金鑰
import os
import openai
import gradio as gr
from zhdate import ZhDate
from datetime import datetime

localrun = False # 上傳到 Space 時要設定成 False
DESKTOP_KEY = False

# 排紫微盤的參考變數
solar_year = 1998
solar_month = 5
solar_day = 18
time_hour = 3
time_min = 14
gender = 0


zi_adjust = 2

'''
排盤有以下幾個步驟

1. 安十二宮

2. 起寅首、定納音五行局

3. 定紫微星

4. 安主星

5. 安四化星

'''

def gen_chart(solar_year, solar_month, solar_day, time_hour, time_min, gender):
    from datetime import timedelta, datetime

    # 六十甲子納音歌
    fiveoldsong = [ 4, 2, 6, 4, 2, 6, 2, 6, 5, 2, 6, 5, 6, 5, 3, 6, 5, 3, 5, 3, 4, 5, 3, 4, 3, 4, 2, 3, 4, 2 ];

    # 五行局
    fiveway = ['水二局','木三局','金四局','土五局','火六局']

    # 紫微星查表
    ziwei_table = [2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,1,1,2,2,3,3,4,4,5,5,2,3,6,3,4,7,4,5,8,5,6,9,6,7,10,7,8,11,8,9,12,9,10,1,10,11,2,11,12,12,5,2,3,1,6,3,4,2,7,4,5,3,8,5,6,4,9,6,7,5,10,7,8,6,11,8,9,7,12,7,12,5,2,3,8,1,6,3,4,9,2,7,4,5,10,3,8,5,6,11,5,9,6,7,12,5,10,7,8,10,7,12,5,2,3,11,8,1,6,3,4,12,9,2,7,4,5,1,10,3,8,5,6,2,11,4,9,6,7];

    # 天府星查表
    tianfu_table = [5,4,3,2,1,12,11,10,9,8,7,6]

    def get_year_hepos(birthdatetime):
        start_year = (birthdatetime.year - 3) % 60
        hs_pos = start_year % 10
        if hs_pos == 0:
            hs_pos = 10
        gb_pos = start_year % 12
        if gb_pos == 0:
            gb_pos = 12
        year_hepos = [hs_pos, gb_pos]
        return year_hepos

    def get_birth_time_epos(birthdatetime):
        if birthdatetime.hour in range(23, 1):
            return 1
        elif birthdatetime.hour in range(1, 3):
            return 2
        elif birthdatetime.hour in range(3, 5):
            return 3
        elif birthdatetime.hour in range(5, 7):
            return 4
        elif birthdatetime.hour in range(7, 9):
            return 5
        elif birthdatetime.hour in range(9, 11):
            return 6
        elif birthdatetime.hour in range(11, 13):
            return 7
        elif birthdatetime.hour in range(13, 15):
            return 8
        elif birthdatetime.hour in range(15, 17):
            return 9
        elif birthdatetime.hour in range(17, 19):
            return 10
        elif birthdatetime.hour in range(19, 21):
            return 11
        elif birthdatetime.hour in range(21, 23):
            return 12
        return 1

    def get_self_palace_epos(birthdatetime, isleap):

        month_position = birthdatetime.month
        hour_position = get_birth_time_epos(birthdatetime)

        #檢查是否為閏月
        if isleap == True:
            if Zwsetting.intercalary_month == 2:
                month_position += 1
            elif Zwsetting.intercalary_month == 3:
                if birthdatetime.day > 15:
                    month_position += 1
        # 直接將月份 +3 的原因是: +2 是為了將寅起調整成子起,另外的 +1 是因為計算時間時本格也算一次,所以 +1 調整回來。
        position = ( month_position + 3 - hour_position )%12
        position = 12 if position == 0 else position

        return position

    def get_body_palace_epos(birthdatetime, isleap):
        
        month_position = birthdatetime.month
        hour_position = get_birth_time_epos(birthdatetime)
        
        #檢查是否為閏月(先不用管閏十二月,最接近的兩年 1889年,2500年)
        if isleap == True:
            if Zwsetting.intercalary_month == 2:
                month_position += 1
            elif Zwsetting.intercalary_month == 3:
                if birthdatetime.day > 15:
                    month_position += 1

        # 直接將月份 +1 的原因是: +2 是為了將寅起調整成子起,另外的 -1 是因為計算時間時本格也算一次,所以 -1 調整回來。
        position = ( month_position + 1 + hour_position )%12
        position = 12 if position == 0 else position
        return position

    def get_yin_hpos(birthdatetime):
        start_year = (birthdatetime.year - 3) % 60
        hs_pos = start_year % 10
        if hs_pos == 0:
            hs_pos = 10
        self_hpos = ((1+hs_pos*2) % 10)
        return self_hpos
    
    #chart_data = solar_year +'/'+  solar_month +'/'+ solar_day +'/'+ str(time_hour)+':'+str(time_min)+'/'+str(gender)
    #print(str(chart_data))

    solar_birth_datetime = datetime(int(solar_year), int(solar_month), int(solar_day), time_hour, time_min)

    #夜子時設定檢查
    if zi_adjust == 2 and time_hour >= 23 :
        solar_birth_datetime = solar_birth_datetime + timedelta(days=1)

    # 跳過 農曆轉換
    #lunar = Zwbase.get_lunar_datetime(solar_birth_datetime)
    #lunar_birth_datetime = LunarDatetime(lunar.lunarYear, lunar.lunarMonth, lunar.lunarDay, solar_birth_datetime.hour, solar_birth_datetime.minute, lunar.isleap)

    # 取得生辰年干支位置
    year_hepos = get_year_hepos(solar_birth_datetime)

    # 取得陰陽性別位置
    #   性別
    if gender == 2:
        gender_pos = 2
    else:
        gender_pos = 3
        
    #   陰陽
    yin_yang_pos = 0 if year_hepos[0] % 2 == 1 else 1


    # 取得生辰地支位置
    birth_time_epos = get_birth_time_epos(solar_birth_datetime)

    # 取得命宮地支位置
    self_palace_epos = get_self_palace_epos(solar_birth_datetime, False) ## 閏年處理 lunar.isleap

    # 取得寅宮天干位置
    yin_hpos = get_yin_hpos(solar_birth_datetime)

    # 取得命宮天干位置
    #   - 計算命宮-寅宮順向距離
    self_yin_dist = 0
    if self_palace_epos >= 3:
        self_yin_dist = self_palace_epos - 3
    else:
        self_yin_dist = self_palace_epos + 9
    #   - 計算命宮天干位置
    self_palace_hpos = 0
    if (self_yin_dist + yin_hpos) > 10:
        self_palace_hpos = (self_yin_dist + yin_hpos) - 10
    else:
        self_palace_hpos = self_yin_dist + yin_hpos


    # 取得身宮位置
    body_palace_epos = get_body_palace_epos(solar_birth_datetime, False)

    # 取得五行局
    fiveway_param_1 = int(( self_palace_hpos + 1) / 2  if self_palace_hpos % 2 == 1 else self_palace_hpos / 2 )
    fiveway_param_2 = int(( self_palace_epos + 1) / 2  if self_palace_epos % 2 == 1 else  self_palace_epos / 2 )
    fiveway_pos = fiveoldsong[(fiveway_param_1 - 1) * 6 + fiveway_param_2 - 1]

    # 取得紫微星位置
    ziwei_pos = ziwei_table[(fiveway_pos -2) * 30 + int(solar_day)-1] ## lunar.lunarDay - 1

    # 取得天府星位置
    tianfu_pos = tianfu_table[ziwei_pos-1]
    outstr=f'紫微在= {ziwei_pos} 五行局= {fiveway_pos} 命宮= {self_palace_epos}'

    return outstr
    
'''
    # 產生 chat(命盤) 物件
    chart = Chart( [self_palace_hpos, self_palace_epos], body_palace_epos)
    chart.birth_year_hepos = year_hepos
    chart.birth_time_epos = birth_time_epos
    chart.yin_hpos = yin_hpos
    chart.yin_yang_gender = [ yin_yang_pos, gender_pos]
    chart.ziwei_pos = ziwei_pos
    chart.fiveway_pos = fiveway_pos
    chart.lifechart_type = (chart.ziwei_pos -1)*12 + chart.self_palace_hepos[1]

    # 產生十二宮 (一共會產生 13宮,第 0 宮不使用)
    for i in range(0, 13, 1):
        chart.palaces.append(Palace(i))

    # 排(產生)十二個主星
    chart = gen_star(chart, ziwei_pos, tianfu_pos, year_hepos, birth_time_epos, solar_birth_datetime, Fasle) # lunar.isleap

    # 檢查星耀 (第 0 宮不使用)
    for p_index, palace in enumerate(chart.palaces):
        if p_index > 0: 

            age_string = '['+str(palace.age[0])+'~'+str(palace.age[1])+']'
            name_string = '['+str(palace.name)+'-'+str(palace.pos[1])+']'

            for index, star in enumerate(palace.stars):
                star_weight_string = '('+str(Zwsetting.star_weight[star.weight])+')'
    return True
'''

def get_envkey():
    from dotenv import load_dotenv, find_dotenv
    _ = load_dotenv(find_dotenv()) # read local .env file
    openai.api_key = os.environ['OPENAI_API_KEY']
    print(openai.api_key)
    if openai.api_key:
       DESKTOP_KEY = openai.api_key 
    print(DESKTOP_KEY)

if localrun:
    get_envkey()

# 定義地支對應的時間區間
z_mapping = {
        "1": "子",
        "2": "丑",
        "3": "寅",
        "4": "卯",
        "5": "辰",
        "6": "巳",
        "7": "午",
        "8": "未",
        "9": "申",
        "10": "酉",
        "11": "戌",
        "12": "亥",
        "0": "夜子"
    } 

## AI 建議
def get_advice(bmi,temp, API_KEY, model="gpt-3.5-turbo"):
    if API_KEY:
        openai.api_key = API_KEY
    else:
        openai.api_key = DESKTOP_KEY
    print(openai.api_key)
    bmi = '' #未來再說
    gw_main_star = '像一個獨裁霸道的君王,無法聽進別人的意見'
    gw_main_star = f'''天機星像一個足智多謀的軍師,ㄧ有時候會考慮太多而失去前進的勇氣
正面特徵

聰明伶俐:天機星是一顆智慧之星,因此命宮有天機的人通常聰明伶俐,善於思考。
善於交際:天機星也代表善於交際,因此命宮有天機的人通常口才好,能夠與他人建立良好的關係。
善於謀劃:天機星也代表機謀,因此命宮有天機的人通常善於謀劃,能夠在事業上取得成功。
適應能力強:天機星也代表變通,因此命宮有天機的人通常適應能力強,能夠在不同的環境中生存。
多才多藝:天機星也代表多才多藝,因此命宮有天機的人通常興趣愛好廣泛,能夠在多個領域取得成就。
人緣好:天機星也代表人緣,因此命宮有天機的人通常人緣好,能夠得到他人的幫助。
善解人意:天機星也代表體貼,因此命宮有天機的人通常善解人意,能夠理解他人的感受。
直覺敏銳:天機星也代表直覺,因此命宮有天機的人通常直覺敏銳,能夠在遇到問題時做出正確的判斷。

負面特徵

心神不定:天機星也代表不安,因此命宮有天機的人通常心神不定,容易三心二意。
缺乏耐心:天機星也代表急躁,因此命宮有天機的人通常缺乏耐心,容易半途而廢。
容易鑽牛角尖:天機星也代表鑽研,因此命宮有天機的人通常容易鑽牛角尖,容易陷入死胡同。
容易受他人影響:天機星也代表隨波逐流,因此命宮有天機的人通常容易受他人影響,容易失去自我。
好高騖遠:天機星也代表理想化,因此命宮有天機的人通常好高騖遠,容易不切實際。
    '''
    messages = [{"role": "system", "content": "你是一個心理權威,你會根據用戶的個性,提供至少3個,不超過5個建議。"},
                {"role": "user", "content": f'我的人生以紫微斗數星象來論述是 {gw_main_star}. 請總結該論述,提出幾條相對重要的重要特徵,給出一些待人處事的建議?'},]
    response = openai.chat.completions.create(
        model=model,
        max_tokens=1000,
        messages=messages,
        temperature=temp, # this is the degree of randomness of the model's output
    )
    return response.choices[0].message.content

## 健身計畫
def get_gym(bmi,slide, temp, API_KEY, model="gpt-3.5-turbo"):
    if API_KEY:
        openai.api_key = API_KEY
    else:
        openai.api_key = DESKTOP_KEY
    print(openai.api_key)
    messages = [{"role": "system", "content": "You are a great fitness coach and \
                 you will give users great fitness plans."},
                {"role": "user", "content": f'My BMI is {bmi}. I want a {slide}-point weight\
                  loss plan, from 1 to 10. The higher the number, the faster the weight loss.'},]
    response = openai.chat.completions.create(
        model=model,
        max_tokens=200,
        messages=messages,
        temperature=temp, # this is the degree of randomness of the model's output
    )
    return response.choices[0].message.content

def GWAI(year, month, day, btime, sex) -> datetime:
    dt_date1 = datetime(int(year), int(month), int(day))
    date_lunar = ZhDate.from_datetime(dt_date1)
    bstr = str(date_lunar)
    
    hour = int(btime.split(":")[0])
    if hour >= 23:
        z = 0
    else:
        z = int((hour + 1) / 2) + 1
    result=z_mapping[str(z)]
    output=(bstr.replace('农历','農曆') + " " + result + "時")

    import re
    match = re.search(r'(\d+)年(\d+)月(\d+)日', output)

    if match:
        my_year = match.group(1)
        my_month = match.group(2)
        my_day = match.group(3)

    print('<<',my_year,my_month,my_day,'>>')
    output2=gen_chart(int(my_year), int(my_month), int(my_day), hour, int(10), int(2))
    return output,output2



# 建立 components
year = gr.Textbox(
    label="生年",
    info="輸入你的西元出生年份",
    placeholder="Input your birth year here...")

month = gr.Textbox(
    label="生月",
    info="輸入你的出生月份",
    placeholder="Input your birthday month here...",)

day = gr.Textbox(
    label="生日",
    info="輸入你的出生日子",
    placeholder="Input your birthday day here...",)

btime = gr.Textbox(
    label="生時",
    info="輸入你的出生時間 HH:MM (幾點及約略幾分即可,請用24小時制)",
    placeholder="Input your birth time here...",)

sex = gr.Textbox(
    label="性別",
    info="輸入你是男生或女生",
    placeholder="Input you are male or female here...",)

output_gwai = gr.Textbox(
    value="",
    label="你的農曆生日及出生時辰",
    info="這是從西元換算出的農曆生日及出生時辰",
    placeholder="Date & Time")

output2_gwai = gr.Textbox(
    value="",
    label="你的紫微斗數命宮星象",
    info="這是你的紫微斗數命盤上,命宮裡的主星的資訊",
    placeholder="Stars in your master plate.")

advice = gr.Textbox(
    label="人生建議 Friendly Advice",
    info="AI 紫微根據你的命盤星象所提供的人生建議",
    placeholder="Ouput Text here...",
    lines=5,)

btn = gr.Button(
    value="計算農曆生日及八字時辰",
    variant="primary", scale=1)

btn_advice  = gr.Button(
    value="AI 紫微的人生建議",
    variant="primary", scale=2)

btn_gym = gr.Button(
    value="AI 紫微聊天室",
    variant="primary", scale=1)

key_box = gr.Textbox(
    label="輸入你的 API 金鑰",
    info="You have to provide your own OPENAI_API_KEY for this app to function properly",
    placeholder="Type OpenAI API KEY here...",
    type="password")

temperature = gr.Slider(
    minimum=0,
    maximum=1.0,
    value=0.3,
    step=0.05,
    label="Temperature",
    info=(
        "Temperature controls the degree of randomness in token selection. Lower "
        "temperatures are good for prompts that expect a true or correct response, "
        "while higher temperatures can lead to more diverse or unexpected results. "
    ),
)

with gr.Blocks() as demo:
    gr.Markdown("""
    # AI 紫微
    起手式 - 轉換西元生日到農曆出生時辰
    """)
    with gr.Column():
        with gr.Row():
            year.render()  # 顯示年
            month.render() # 顯示月
            day.render() # 顯示日
            btime.render() # 顯示時
            sex.render() # 顯示性別
        
        with gr.Row():
            output_gwai.render() # 顯示農曆生日欄
            output2_gwai.render()

        btn.render() # 顯示農曆生日值結果
        btn.click(fn=GWAI, 
                     inputs=[year, month, day, btime, sex], 
                     outputs=[output_gwai,output2_gwai])

        advice.render() # 顯示AI建議結果的文字框
        
        with gr.Row(): 
            key_box.render() # 顯示API金鑰輸入框
            btn_advice.render() # 顯示AI建議按鈕
            btn_advice.click(fn=get_advice, inputs=[output_gwai,temperature,key_box], outputs=advice)
            #btn_gym.render() # 顯示AI健身計畫按鈕
            #btn_gym.click(fn=get_gym, inputs=[output_gwai,slider,temperature, key_box], outputs=advice)
    
        with gr.Accordion("settings", open=True):
            temperature.render()

demo.launch()