File size: 7,118 Bytes
86979a0
 
 
 
 
 
 
 
 
c38adcf
 
 
86979a0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c38adcf
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
import gradio as gr
import requests
import os
import time

# Model configuration
MODEL_ID = "chendren/deepseek-dnd-lora"
API_URL = f"https://api-inference.huggingface.co/models/{MODEL_ID}"

# Use environment variable for the token
# This will be set in the Hugging Face Space settings
headers = {"Authorization": f"Bearer {os.environ.get('HUGGINGFACE_TOKEN', '')}"}

# Example prompts
example_prompts = [
    "Create a D&D character with the following details: Race: Half-Elf, Class: Bard, Background: Entertainer",
    "Design a D&D adventure hook set in a dark forest with a mysterious cult",
    "Create a magical item for D&D 5e that would be suitable for a level 5 rogue",
    "Write a description for a fantasy tavern in a D&D setting called 'The Dragon\'s Rest'",
    "Create a D&D monster stat block for a new type of undead creature called 'Mist Wraith'",
    "Write a backstory for a Dragonborn Paladin who follows the Oath of Vengeance",
]

def generate_text(prompt, temperature=0.7, max_length=500, top_p=0.9, top_k=50, rep_penalty=1.1):
    """
    Generate text using the Hugging Face Inference API
    If the API fails, provide instructions for manual testing
    """
    full_prompt = f"You are a Dungeons & Dragons assistant. {prompt}"
    
    payload = {
        "inputs": full_prompt,
        "parameters": {
            "max_new_tokens": int(max_length),
            "temperature": float(temperature),
            "top_p": float(top_p),
            "top_k": int(top_k),
            "repetition_penalty": float(rep_penalty),
            "do_sample": True
        }
    }
    
    try:
        response = requests.post(API_URL, headers=headers, json=payload)
        
        if response.status_code == 200:
            result = response.json()
            if isinstance(result, list) and len(result) > 0:
                if "generated_text" in result[0]:
                    return result[0]["generated_text"]
                else:
                    return str(result[0])
            else:
                return str(result)
                
        elif response.status_code == 503:
            return (
                "⏳ The model is still loading or being processed by Hugging Face. "
                "This is normal for new or infrequently used models. Please try again in a few minutes.\n\n"
                "If the problem persists, you can also try using the model directly via code: "
                "https://huggingface.co/chendren/deepseek-dnd-lora#using-the-transformers-library"
            )
            
        else:
            return (
                f"⚠️ Error: API returned status code {response.status_code}\n\n"
                f"Response: {response.text}\n\n"
                "You can try again later or use the model directly with the code provided here: "
                "https://huggingface.co/chendren/deepseek-dnd-lora"
            )
            
    except Exception as e:
        return (
            f"⚠️ An error occurred: {str(e)}\n\n"
            "Check if the model is available or try using the model directly using the code examples: "
            "https://huggingface.co/chendren/deepseek-dnd-lora"
        )

# Create the Gradio interface
with gr.Blocks(title="D&D Content Generator", css="footer {visibility: hidden}") as demo:
    gr.Markdown(
        """
        # 🐉 Dungeons & Dragons Content Generator
        
        This demo uses the [DeepSeek-R1-Distill-Qwen-7B](https://huggingface.co/deepseek-ai/DeepSeek-R1-Distill-Qwen-7B) model fine-tuned on D&D content.
        
        Enter a prompt related to D&D content creation, or try one of the examples below.
        
        ### Model Details
        - Base model: [deepseek-ai/DeepSeek-R1-Distill-Qwen-7B](https://huggingface.co/deepseek-ai/DeepSeek-R1-Distill-Qwen-7B)
        - Fine-tuned with LoRA on 500 examples of D&D content
        - Specialized for creating characters, adventures, items, and more for D&D
        
        [View Model on Hugging Face](https://huggingface.co/chendren/deepseek-dnd-lora)
        """
    )
    
    with gr.Row():
        with gr.Column():
            prompt = gr.Textbox(
                label="Prompt",
                placeholder="Enter your D&D content request...",
                lines=4
            )
            
            with gr.Row():
                submit_btn = gr.Button("Generate", variant="primary")
                clear_btn = gr.Button("Clear")
            
            with gr.Accordion("Advanced Parameters", open=False):
                temperature = gr.Slider(
                    minimum=0.1, maximum=1.5, value=0.7, step=0.1,
                    label="Temperature (creativity)",
                    info="Higher values produce more creative but potentially less coherent output"
                )
                max_length = gr.Slider(
                    minimum=100, maximum=1000, value=500, step=50,
                    label="Maximum Length",
                    info="Maximum number of tokens to generate"
                )
                top_p = gr.Slider(
                    minimum=0.1, maximum=1.0, value=0.9, step=0.1,
                    label="Top-p",
                    info="Nucleus sampling probability threshold"
                )
                top_k = gr.Slider(
                    minimum=1, maximum=100, value=50, step=5,
                    label="Top-k",
                    info="Number of highest probability tokens to consider"
                )
                rep_penalty = gr.Slider(
                    minimum=1.0, maximum=2.0, value=1.1, step=0.1,
                    label="Repetition Penalty",
                    info="Penalizes repeated tokens (higher = less repetition)"
                )
        
        with gr.Column():
            output = gr.Textbox(
                label="Generated Output",
                placeholder="D&D content will appear here...",
                lines=20
            )
    
    gr.Examples(
        examples=example_prompts,
        inputs=prompt,
        outputs=output,
        fn=lambda x: generate_text(x),
        cache_examples=False
    )
    
    gr.Markdown(
        """
        ### Usage Tips
        - Be specific in your prompts, including details like race, class, and level where applicable
        - For character creation, specify race, class, background, and any other details
        - For adventure hooks, specify setting, theme, and target party level
        - For magic items, specify item type, rarity, and intended user
        
        ### Credits
        - Base model: [DeepSeek-R1-Distill-Qwen-7B](https://huggingface.co/deepseek-ai/DeepSeek-R1-Distill-Qwen-7B)
        - Fine-tuned by: [chendren](https://huggingface.co/chendren)
        """
    )
    
    # Set up event handlers
    submit_btn.click(
        fn=generate_text,
        inputs=[prompt, temperature, max_length, top_p, top_k, rep_penalty],
        outputs=output
    )
    
    clear_btn.click(
        fn=lambda: ("", ""),
        inputs=[],
        outputs=[prompt, output]
    )

# Launch the app
if __name__ == "__main__":
    demo.launch()