【ai塔罗牌-生命之树】【azure openai】【python】交互塔罗牌demo
塔罗牌抽取机制说明
对于"生命之树"玩法,这是一种特定的塔罗牌阵法,基于卡巴拉的生命之树,通常会有10个位置,每个位置对应生命之树的一个节点,有不同的含义
1.程序初始化时会创建一副完整的塔罗牌,包含:
- 22张大阿卡纳牌(Major Arcana)
- 56张小阿卡纳牌(Minor Arcana)
2.在开始占卜会话时,系统会对这副78张牌进行洗牌(随机打乱顺序)
3. 然后,用户依次为生命之树的10个位置抽取牌,每抽取一张牌,该牌就会从牌组中移除
4.所以每次抽取的是不重复的牌,但没有特定位置必须抽特定类型牌的限制
5.被抽走的牌不会返回牌组,除非开始新的一轮占卜
这种机制符合传统塔罗牌占卜的做法,因为在实际的塔罗占卜中,通常是从同一副牌中不重复地抽取所需的牌。
运行结果演示:

🌟 塔罗牌解读 🌟
塔罗牌生命之树牌阵是一个深奥而复杂的解读工具,它通过十个不同的维度来分析一个问题的整体情况。以下是对您抽到的牌阵的详细解读,以及它对您粉丝增长问题的启示。
---
### **1. 王冠 (Kether) - 事情的精神本质和最高目标**
**Ace的钱币 (逆位)**
这张牌逆位的状态暗示了您对于粉丝增长的目标可能存在某种不稳定的基础,或者潜藏着某些尚未充分挖掘的潜力。Ace的钱币本质上代表新的机会和实际成就,但逆位表明您的粉丝增长可能并非纯粹依靠外界的物质支持,而需要您重新审视自己的策略和内心动机。或许您需要更加明确自己创造内容的价值和意义,而不仅仅是关注数字的增长。---
### **2. 智慧 (Chokmah) - 事情的动力和创造力**
**9的权杖 (正位)**
这张牌表明您已经在内容创作的道路上付出了极大的努力,并拥有坚韧不拔的精神。9的权杖代表一种战斗到最后的状态,虽然您可能感到疲惫,但您的坚持是粉丝增长的核心动力。继续保持这种专注和努力,避免被短期的挫折所击退,您的粉丝数增长是可期的。---
### **3. 理解 (Binah) - 事情的形式和限制**
**5的权杖 (逆位)**
这张牌逆位显示出某种冲突的缓解或者竞争的减弱。可能您在内容创作的领域中,竞争正在减少,或者您已经找到了一种方法与其他创作者共存,而不是激烈对抗。这为您的粉丝增长提供了更为稳定的环境,但同时也提示您需要避免内部的混乱或方向不明确。---
### **4. 仁慈 (Chesed) - 建设性影响和资源**
**王后的圣杯 (正位)**
王后的圣杯是情感和直觉的象征。在这个位置上,它表明您拥有一种真诚和吸引人的特质,这可能是您内容创作中最强大的资源。您的粉丝喜欢您内容中流露出的情感或真诚,这为您的增长提供了坚实的基础。继续保持这种真诚的态度,同时倾听粉丝的需求和反馈,您的影响力会逐步扩大。---
### **5. 力量 (Geburah) - 面临的挑战和障碍**
**8的圣杯 (逆位)**
这张牌逆位通常暗示一种对变化的抗拒,或者难以从过去的某些情绪中抽身。您可能在某些方面拘泥于旧的内容形式或创作风格,而这可能阻碍了您的粉丝增长。要突破这一障碍,您需要勇敢面对自己的舒适区,尝试一些新的创作方向或方法。---
### **6. 美丽 (Tiphereth) - 核心平衡点和内在和谐**
**3的圣杯 (逆位)**
这张牌逆位提示您可能在团队协作或社交互动中感到某种不和谐。或许您需要更多地与粉丝互动,或者更积极地参与创作者社区,以获得更深层次的支持和联结。如果您的内容创作较为孤立,尝试与其他创作者合作,可能会带来新的粉丝群体。---
### **7. 胜利 (Netzach) - 情感和关系影响**
**Ace的权杖 (正位)**
这是一个非常积极的牌,表明您在情感上已经准备好迎接新的挑战。Ace的权杖象征着热情、活力和新开始。它告诉您,您的粉丝增长将受到情感上的强烈驱动,只要您能保持这种激情,并创造出具有感染力的内容,粉丝的增长是不可避免的。---
### **8. 荣耀 (Hod) - 理性思考和交流**
**V - 教皇 (正位)**
教皇是知识和传统的象征。在这个位置上,它暗示您需要运用系统性的思维和策略来规划您的内容创作。或许您可以考虑建立更明确的主题框架或内容体系,或者通过一些教育性、指导性的内容吸引更多粉丝。教皇还暗示您可能需要寻求某种导师或榜样的指导。---
### **9. 基础 (Yesod) - 潜意识和隐藏的影响**
**X - 命运之轮 (逆位)**
命运之轮逆位表明当前的粉丝增长可能受到外界环境的不稳定影响。或许您的平台算法、创作领域的变化、或某些不可控的因素正在拖缓您的增长。这张牌提示您接受不确定性,并主动调整策略以应对变化。---
### **10. 王国 (Malkuth) - 最终的物质结果**
**XVIII - 月亮 (逆位)**
月亮逆位表明事情的结果将逐渐变得清晰,但在此之前可能会经历一段迷茫或不确定的时期。粉丝增长的过程可能不像您预期的那样快速,但随着时间推移,您将逐渐看到努力的回报。保持耐心,专注于内容质量,您的粉丝数达到2000的目标是可实现的。---
### **整体启示与大概时间预测**
从牌阵整体来看,您的粉丝增长并非一蹴而就,需要持续的努力和策略调整。关键牌如王后的圣杯、Ace的权杖和教皇显示您具备足够的资源和潜力,但同时也需要克服8的圣杯逆位和命运之轮逆位所带来的阻力。月亮逆位提示您的目标可能会在迷雾散去后逐渐显现。结合这些牌的能量流动,大概的时间段可能会是在**2025年5月中旬至6月初**之间(约8至12周后)。这一时间段将是您努力的成果开始显现的节点,但具体速度仍取决于您的行动和外部环境的变化。
---
希望这次解读能为您提供启发和指导!塔罗牌只是一个象征性的工具,最终的结果还是取决于您的坚持和智慧。祝您的粉丝数早日达到目标!
感谢使用塔罗占卜服务,祝你好运!
还是蛮好玩的,代码奉上,改一下openai的key就可以直接玩了~
在azure中快速查找key和demo:【保姆级教程】如何在azure里快速找到openai的key和demo_microsoft azure openai appkey-CSDN博客文章浏览阅读159次,点赞8次,收藏5次。先在主页里找到然后打开然后点击左侧-聊天-选好要用的模型 - 查看代码选择密钥验证往下滑,找到和可以直接在该示例中看到完成。_microsoft azure openai appkeyhttps://blog.csdn.net/weixin_51711034/article/details/145935201?spm=1001.2014.3001.5501
代码结构:
- tarot_gpt.py
- azure_openai_client.py
#tarot_gpt.py
import random
import time
from azure_openai_client import AzureOpenAIClient
class TarotGPT:
def __init__(self):
"""初始化塔罗牌系统"""
# 创建 Azure OpenAI 客户端,设置系统提示
system_prompt = """你是一位精通塔罗牌解读的AI占卜师。
请根据用户提问和抽到的塔罗牌进行专业、详细的解读。
解读应包含牌的基本含义、在当前位置的特殊意义,以及对用户问题的针对性回答。
回答要有神秘感,同时务必尊重用户,不要做出绝对预测或提供有害建议。"""
self.client = AzureOpenAIClient(system_prompt=system_prompt)
# 塔罗牌列表 (大阿卡纳牌)
self.major_arcana = [
"0 - 愚者", "I - 魔术师", "II - 女祭司", "III - 女皇", "IV - 皇帝",
"V - 教皇", "VI - 恋人", "VII - 战车", "VIII - 力量", "IX - 隐士",
"X - 命运之轮", "XI - 正义", "XII - 倒吊人", "XIII - 死神", "XIV - 节制",
"XV - 恶魔", "XVI - 塔", "XVII - 星星", "XVIII - 月亮", "XIX - 太阳",
"XX - 审判", "XXI - 世界"
]
# 小阿卡纳牌 (四个花色,每个14张)
suits = ["权杖", "圣杯", "宝剑", "钱币"]
ranks = ["Ace", "2", "3", "4", "5", "6", "7", "8", "9", "10", "侍从", "骑士", "王后", "国王"]
self.minor_arcana = [f"{rank}的{suit}" for suit in suits for rank in ranks]
# 完整的塔罗牌组
self.tarot_deck = self.major_arcana + self.minor_arcana
# 生命之树位置的含义
self.tree_of_life_positions = [
"王冠 (Kether) - 事情的精神本质和最高目标",
"智慧 (Chokmah) - 事情的动力和创造力",
"理解 (Binah) - 事情的形式和限制",
"仁慈 (Chesed) - 建设性影响和资源",
"力量 (Geburah) - 面临的挑战和障碍",
"美丽 (Tiphereth) - 核心平衡点和内在和谐",
"胜利 (Netzach) - 情感和关系影响",
"荣耀 (Hod) - 理性思考和交流",
"基础 (Yesod) - 潜意识和隐藏的影响",
"王国 (Malkuth) - 最终的物质结果"
]
def shuffle_deck(self):
"""洗牌"""
random.shuffle(self.tarot_deck)
def draw_card(self):
"""抽一张牌"""
if not self.tarot_deck:
return "牌组已空"
card = self.tarot_deck.pop(0)
is_reversed = random.choice([True, False])
return f"{card} {'(逆位)' if is_reversed else '(正位)'}"
def interpret_cards(self, question, cards, positions):
"""使用AI解读抽到的牌"""
# 构建提示
prompt = f"用户想知道:{question}\n\n他们使用生命之树牌阵抽到了以下塔罗牌:\n"
for i, (card, position) in enumerate(zip(cards, positions)):
prompt += f"{i+1}. {position}:{card}\n"
# print(prompt)
prompt += "\n请对这个生命之树牌阵进行详细解读,分析每张牌在各自位置的含义,以及对用户问题的整体启示。"
# 调用AI进行解读
messages = [
{"role": "system", "content": [{"type": "text", "text": self.client.default_chat_prompt[0]["content"][0]["text"]}]},
{"role": "user", "content": [{"type": "text", "text": prompt}]}
]
response = self.client.chat_completion(
messages=messages,
max_tokens=2000,
temperature=0.7
)
return response.choices[0].message.content
def run_session(self):
"""运行塔罗牌会话"""
print("🔮 欢迎使用塔罗占卜 - 生命之树牌阵 🔮")
print("这种牌阵将帮助你全面了解你所询问的问题")
print("我们将抽取10张牌,分别对应生命之树的10个位置\n")
question = input("请告诉我,你想了解什么问题? ")
print("\n开始洗牌...\n")
time.sleep(1)
self.shuffle_deck()
cards = []
print("请依次抽取10张牌:\n")
for i, position in enumerate(self.tree_of_life_positions):
input(f"按Enter抽取第{i+1}张牌 - {position.split(' - ')[0]}")
card = self.draw_card()
cards.append(card)
print(f"你抽到了:{card}")
print(f"位置:{position}")
print("-" * 50)
print("\n所有牌已抽取完毕,正在解读...\n")
interpretation = self.interpret_cards(question, cards, self.tree_of_life_positions)
print("🌟 塔罗牌解读 🌟\n")
print(interpretation)
print("\n感谢使用塔罗占卜服务,祝你好运!")
if __name__ == "__main__":
tarot = TarotGPT()
tarot.run_session()
#azure_openai_client.py
import os
import base64
import re
from openai import AzureOpenAI
from typing import List, Dict, Optional, Union
class AzureOpenAIClient:
def __init__(
self,
endpoint: str = "https://xxxxx.openai.azure.com/",
deployment: str = "gpt-4o",#我用的4o,也可以换乘别的模型
api_key: Optional[str] = None,
system_prompt: str = None
):
"""
初始化 Azure OpenAI 客户端
Args:
endpoint: Azure OpenAI 服务端点
deployment: 部署名称
api_key: API 密钥,如果为 None 则从环境变量获取
system_prompt: 系统提示词,如果为 None 则使用默认提示
"""
self.endpoint = endpoint
self.deployment = deployment
self.api_key = api_key or os.getenv(
"AZURE_OPENAI_API_KEY",
"xxxxxxxxxxxxxx"#换成你的key
)
self.client = AzureOpenAI(
azure_endpoint=self.endpoint,
api_key=self.api_key,
api_version="2024-05-01-preview"
)
# 使用传入的系统提示词或默认提示词
default_prompt_text = "你是一个帮助用户查找信息的 AI 助手。"
if system_prompt:
default_prompt_text = system_prompt
self.default_chat_prompt = [
{
"role": "system",
"content": [
{
"type": "text",
"text": default_prompt_text
}
]
}
]
def encode_image(self, image_path: str) -> str:
"""
将图片编码为 base64 字符串
Args:
image_path: 图片路径
Returns:
base64 编码的图片字符串
"""
with open(image_path, 'rb') as image_file:
return base64.b64encode(image_file.read()).decode('ascii')
def chat_completion(
self,
messages: Optional[List[Dict]] = None,
max_tokens: int = 200,
temperature: float = 0.7,
top_p: float = 0.95,
frequency_penalty: float = 0,
presence_penalty: float = 0,
stop: Optional[Union[str, List[str]]] = None,
stream: bool = False
):
"""
生成聊天完成
Args:
messages: 聊天消息列表,如果为 None 则使用默认提示
max_tokens: 生成的最大标记数
temperature: 采样温度
top_p: 核采样概率
frequency_penalty: 频率惩罚
presence_penalty: 存在惩罚
stop: 停止序列
stream: 是否使用流式响应
Returns:
聊天完成响应
"""
if messages is None:
messages = self.default_chat_prompt
completion = self.client.chat.completions.create(
model=self.deployment,
messages=messages,
max_tokens=max_tokens,
temperature=temperature,
top_p=top_p,
frequency_penalty=frequency_penalty,
presence_penalty=presence_penalty,
stop=stop,
stream=stream
)
return completion
@staticmethod
def clean_markdown_for_speech(text: str) -> str:
"""
清理Markdown格式,使文本适合语音输出
Args:
text: 包含可能的Markdown格式的文本
Returns:
清理后的文本
"""
# 移除星号加粗
text = re.sub(r'\*\*(.*?)\*\*', r'\1', text)
# 移除单星号斜体
text = re.sub(r'\*(.*?)\*', r'\1', text)
# 移除下划线的强调标记
text = re.sub(r'__(.*?)__', r'\1', text)
text = re.sub(r'_(.*?)_', r'\1', text)
# 移除代码块标记 ```
text = re.sub(r'```(\w*\n)?(.*?)```', r'\2', text, flags=re.DOTALL)
# 移除行内代码标记 `
text = re.sub(r'`(.*?)`', r'\1', text)
# 处理标题 (# 标题)
text = re.sub(r'^#+\s+(.*?)$', r'\1', text, flags=re.MULTILINE)
# 处理列表标记,保留数字/符号但删除可能的强调
# 例如: "1. **项目**:" 变成 "1. 项目:"
return text