i am getting the symbols like astericks(* or **) in my code and also i am getting these words in the document "BOLD" , "ITALIC" etc...please fix this and give me the correct code...here is my app.py code
"
from flask import Flask, render_template, request, jsonify, send_file
import google.generativeai as genai
from dotenv import load_dotenv
import os
from werkzeug.utils import secure_filename
from PIL import Image
import PIL
import io
from io import BytesIO
import logging
from langdetect import detect
import requests
from requests import get
from google.generativeai.types import GenerationConfig 
from markdown import markdown
from google.generativeai.types import GenerationConfig, HarmCategory, HarmBlockThreshold
import re
import json
from mailjet_rest import Client
from pdf2image import convert_from_bytes
from docx import Document
from docx.shared import Inches
import tempfile
import PyPDF2
import base64
from docx import Document
from docx.shared import Inches, Pt
from docx.enum.style import WD_STYLE_TYPE
from docx.oxml import OxmlElement
from docx.oxml.ns import qn
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.shared import RGBColor
import fitz  # PyMuPDF

app = Flask(__name__)

# Load environment variables
load_dotenv()
mail_API_KEY = os.environ.get("mail_API_KEY")
mail_API_SECRET = os.environ.get("mail_API_SECRET")
mailjet = Client(auth=(mail_API_KEY, mail_API_SECRET), version='v3.1')
api_key = ""
unsplash_api_key = os.getenv('UNSPLASH_API_KEY')
API_KEY = os.getenv('OPENWEATHERMAP_API_KEY')

# Set up logging
logging.basicConfig(level=logging.INFO)

# Configure the Google Generative AI API
genai.configure(api_key=api_key)

# Session key
user_data = {}  # Dictionary to store user data

# Generation configurations
generation_config = GenerationConfig(
    temperature=0.9,
    top_p=1,
    top_k=1,
    max_output_tokens=2048,
    candidate_count=1
)
generation_config_health = GenerationConfig(
    temperature=0.7,
    top_p=1,
    top_k=1,
    max_output_tokens=512,
    candidate_count=1
)

# Safety Settings
safety_settings = {
    HarmCategory.HARM_CATEGORY_HATE_SPEECH: HarmBlockThreshold.BLOCK_NONE,
    HarmCategory.HARM_CATEGORY_HARASSMENT: HarmBlockThreshold.BLOCK_NONE,
    HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT: HarmBlockThreshold.BLOCK_NONE,
    HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT: HarmBlockThreshold.BLOCK_NONE,
}

# Create model instances
chat_model = genai.GenerativeModel("gemini-1.5-flash", generation_config=generation_config)
chef_model = genai.GenerativeModel("gemini-1.5-flash", generation_config=generation_config)
story_model = genai.GenerativeModel("gemini-1.5-flash", generation_config=generation_config)
psychology_model = genai.GenerativeModel("gemini-1.5-flash", generation_config=generation_config)
code_model = genai.GenerativeModel("gemini-1.5-flash", generation_config=generation_config)
algorithm_model = genai.GenerativeModel("gemini-1.5-flash", generation_config=generation_config)
model_vision = genai.GenerativeModel('gemini-1.5-flash', generation_config=generation_config_health)
model_text = genai.GenerativeModel('gemini-pro', generation_config=generation_config_health)
model = genai.GenerativeModel('gemini-1.5-flash')

@app.route('/')
def index():
    return render_template('index.html')



def format_response(response_text):
    """Formats the response text for display."""
    lines = [line.strip() for line in response_text.split('\n') if line.strip()]
    formatted_text = '<br>'.join(lines)
    return formatted_text

# ... [Other route handlers remain unchanged] ...

# Document summarizer with improved formatting
import tempfile
import time
from threading import Lock
from docx.enum.text import WD_ALIGN_PARAGRAPH, WD_BREAK
from docx.enum.table import WD_ALIGN_VERTICAL

REQUEST_LIMIT = 15  # Adjust as needed for Vercel
TIME_WINDOW = 60
request_count = 0
last_request_time = 0
rate_limit_lock = Lock()

def process_pdf_in_batches(file):
    """Processes PDF in batches to avoid exceeding Vercel's time limit"""
    pdf_document = fitz.open(stream=file.read(), filetype="pdf")
    total_pages = len(pdf_document)
    all_summaries = []
    batch_size = 1  # Process one page at a time

    for i in range(0, total_pages, batch_size):
        batch_texts = []
        batch_images = []
        for page_num in range(i, min(i + batch_size, total_pages)):
            page = pdf_document[page_num]
            text = page.get_text("text")
            batch_texts.append(text)

            # Image processing
            image_list = page.get_images(full=True)
            for img_index, img in enumerate(image_list):
                xref = img[0]
                base_image = pdf_document.extract_image(xref)
                image_bytes = base_image["image"]
                img = Image.open(io.BytesIO(image_bytes))
                batch_images.append(img)  # Directly append PIL Image

        batch_summary = generate_summary(batch_texts, batch_images)
        all_summaries.append(batch_summary)
        time.sleep(1)  # Adjust sleep based on response time

    final_summary = "\n\n".join(all_summaries)
    return final_summary, total_pages

def rate_limited(func):
    def wrapper(*args, **kwargs):
        global request_count, last_request_time
        with rate_limit_lock:
            current_time = time.time()
            if current_time - last_request_time > TIME_WINDOW:
                request_count = 0
                last_request_time = current_time

            request_count += 1
            if request_count > REQUEST_LIMIT:
                remaining_time = TIME_WINDOW - (current_time - last_request_time)
                return jsonify({'error': f'Rate limit exceeded. Please try again in {int(remaining_time)} seconds.'}), 429

            last_request_time = current_time
        return func(*args, **kwargs)

    return wrapper

@app.route('/document_summarizer', methods=['GET', 'POST'])
def document_summarizer():
    return render_template('document_summarizer.html')

def process_pdf(file):
    pdf_document = fitz.open(stream=file.read(), filetype="pdf")
    images = []
    texts = []

    for page_num in range(len(pdf_document)):
        page = pdf_document[page_num]
        # Extract text
        text = page.get_text()
        texts.append(text)

        # Extract images
        image_list = page.get_images(full=True)
        for img_index, img in enumerate(image_list):
            xref = img[0]
            base_image = pdf_document.extract_image(xref)
            image_bytes = base_image["image"]
            # Convert to base64
            image_base64 = base64.b64encode(image_bytes).decode('utf-8')
            images.append(image_base64)

    return texts, images

def generate_summary(texts, images):
    # Modified prompt to encourage better formatting
    prompt = [
        """Summarize the following text, incorporating details from any included images.
        Ensure that the summary is well-structured with clear headings and subheadings.
        Use the following formatting guidelines:

        - Use 'TITLE: [Your Title]' for main sections.
        - Use 'SUBTITLE: [Your Subtitle]' for subsections.
        - For emphasis, use 'BOLD:[Your Text]' to make the text bold.
        - For important points, use 'ITALIC:[Your Text]' to italicize the text.
        - For lists, use 'LIST_ITEM: [Your List Item]' at the start of each item.
        - For tables, present data in a structured format using 'TABLE_START', 'TABLE_ROW', and 'TABLE_END' tags.

        Example:

        TITLE: Introduction
        SUBTITLE: Background
        BOLD: This is an important concept.
        ITALIC: Note this subtle point.
        LIST_ITEM: First point
        LIST_ITEM: Second point
        TABLE_START
        TABLE_ROW: Column1 | Column2 | Column3
        TABLE_ROW: Data1 | Data2 | Data3
        TABLE_END

        Use simple and easy English. Keep the summary concise but informative.
        """,
        "\n".join(texts)
    ]

    for img in images:
        prompt.append(img)
        
    try:
        response = model_vision.generate_content(prompt, safety_settings=safety_settings)
        return response.text
    except Exception as e:
        print(f"Error in Gemini API call: {e}")
        return f"Error summarizing: {e}"

def create_word_document(summary):
    doc = Document()
    
    # Define and customize styles
    styles = doc.styles

    # Title style
    title_style = styles.add_style('CustomTitle', WD_STYLE_TYPE.PARAGRAPH)
    title_style.font.name = 'Calibri Light'
    title_style.font.size = Pt(26)
    title_style.font.bold = True
    title_style.font.color.rgb = RGBColor(31, 56, 100)  # Dark blue
    title_style.paragraph_format.space_before = Pt(24)
    title_style.paragraph_format.space_after = Pt(12)
    title_style.paragraph_format.keep_with_next = True

    # Subtitle style
    subtitle_style = styles.add_style('CustomSubtitle', WD_STYLE_TYPE.PARAGRAPH)
    subtitle_style.font.name = 'Calibri'
    subtitle_style.font.size = Pt(18)
    subtitle_style.font.bold = True
    subtitle_style.font.color.rgb = RGBColor(54, 95, 145)  # Medium blue
    subtitle_style.paragraph_format.space_before = Pt(18)
    subtitle_style.paragraph_format.space_after = Pt(6)
    subtitle_style.paragraph_format.keep_with_next = True

    # Normal text style
    normal_style = styles.add_style('CustomNormal', WD_STYLE_TYPE.PARAGRAPH)
    normal_style.font.name = 'Calibri'
    normal_style.font.size = Pt(12)
    normal_style.paragraph_format.space_after = Pt(8)
    normal_style.paragraph_format.line_spacing = 1.15

    # Bold text style
    bold_style = styles.add_style('CustomBold', WD_STYLE_TYPE.PARAGRAPH)
    bold_style.font.name = 'Calibri'
    bold_style.font.size = Pt(12)
    bold_style.font.bold = True
    bold_style.paragraph_format.space_after = Pt(8)
    bold_style.paragraph_format.line_spacing = 1.15

    # Italic text style
    italic_style = styles.add_style('CustomItalic', WD_STYLE_TYPE.PARAGRAPH)
    italic_style.font.name = 'Calibri'
    italic_style.font.size = Pt(12)
    italic_style.font.italic = True
    italic_style.paragraph_format.space_after = Pt(8)
    italic_style.paragraph_format.line_spacing = 1.15

    # List item style
    list_style = styles.add_style('CustomList', WD_STYLE_TYPE.PARAGRAPH)
    list_style.font.name = 'Calibri'
    list_style.font.size = Pt(12)
    list_style.paragraph_format.left_indent = Inches(0.25)
    list_style.paragraph_format.first_line_indent = Inches(-0.25)
    list_style.paragraph_format.space_after = Pt(4)
    list_style.paragraph_format.line_spacing = 1.15

    # Process the summary
    paragraphs = summary.split('\n')
    in_table = False
    table_rows = []

    for para in paragraphs:
        para = para.strip()

        if para.startswith('TITLE:'):
            if in_table:
                add_table_to_document(doc, table_rows)
                table_rows = []
                in_table = False
            p = doc.add_paragraph(para[6:].strip(), style='CustomTitle')
            p.alignment = WD_ALIGN_PARAGRAPH.CENTER

        elif para.startswith('SUBTITLE:'):
            if in_table:
                add_table_to_document(doc, table_rows)
                table_rows = []
                in_table = False
            p = doc.add_paragraph(para[9:].strip(), style='CustomSubtitle')

        elif para.startswith('BOLD:'):
            if in_table:
                add_table_to_document(doc, table_rows)
                table_rows = []
                in_table = False
            p = doc.add_paragraph(para[5:].strip(), style='CustomBold')

        elif para.startswith('ITALIC:'):
            if in_table:
                add_table_to_document(doc, table_rows)
                table_rows = []
                in_table = False
            p = doc.add_paragraph(para[7:].strip(), style='CustomItalic')

        elif para.startswith('LIST_ITEM:'):
            if in_table:
                add_table_to_document(doc, table_rows)
                table_rows = []
                in_table = False
            p = doc.add_paragraph(para[10:].strip(), style='CustomList')
            p.style.paragraph_format.first_line_indent = Inches(-0.25)
            run = p.add_run()
            run.add_text('• ')
            run.font.size = Pt(10)

        elif para.startswith('TABLE_START'):
            in_table = True
            table_rows = []

        elif para.startswith('TABLE_ROW:'):
            in_table = True
            row_data = [cell.strip() for cell in para[10:].split('|')]
            table_rows.append(row_data)

        elif para.startswith('TABLE_END'):
            add_table_to_document(doc, table_rows)
            table_rows = []
            in_table = False

        elif para:
            if in_table:
                add_table_to_document(doc, table_rows)
                table_rows = []
                in_table = False
            p = doc.add_paragraph(para.strip(), style='CustomNormal')

    if in_table:
        add_table_to_document(doc, table_rows)

    # Add page borders
    set_page_border(doc)

    # Set up the document layout
    section = doc.sections[0]
    section.page_height = Inches(11)
    section.page_width = Inches(8.5)
    section.left_margin = Inches(1)
    section.right_margin = Inches(1)
    section.top_margin = Inches(1)
    section.bottom_margin = Inches(1)

    docx_buffer = io.BytesIO()
    doc.save(docx_buffer)
    docx_buffer.seek(0)
    return docx_buffer

def add_table_to_document(doc, rows):
    if not rows:
        return
    table = doc.add_table(rows=len(rows), cols=len(rows[0]))
    table.style = 'Light List Accent 1'  # Choose a more visually appealing style

    # Set column widths and alignment
    widths = [Inches(2.0)] * len(rows[0])  # Adjust column widths as needed
    for row_idx, row in enumerate(rows):
        for col_idx, cell_text in enumerate(row):
            cell = table.cell(row_idx, col_idx)
            cell.text = cell_text
            cell.width = widths[col_idx]
            cell.vertical_alignment = WD_ALIGN_VERTICAL.CENTER
            cell.paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER

    # Make the header row bold and with background color
    hdr_cells = table.rows[0].cells
    for cell in hdr_cells:
        for paragraph in cell.paragraphs:
            for run in paragraph.runs:
                run.font.bold = True
        shading_elm = OxmlElement('w:shd')
        shading_elm.set(qn('w:fill'), 'D9E1F2')  # Light blue background
        cell._tc.get_or_add_tcPr().append(shading_elm)

    table.allow_autofit = True
    doc.add_paragraph()  # Add space after table

def set_page_border(doc):
    """
    Adds a wider double border to every page of the document.
    """
    for section in doc.sections:
        sectPr = section._sectPr
        pgBorders = OxmlElement('w:pgBorders')
        pgBorders.set(qn('w:offsetFrom'), 'page')
        for border_position in ('top', 'left', 'bottom', 'right'):
            border_el = OxmlElement(f'w:{border_position}')
            border_el.set(qn('w:val'), 'double')
            border_el.set(qn('w:sz'), '24')  # Adjusted border width
            border_el.set(qn('w:space'), '24')
            border_el.set(qn('w:color'), '5B9BD5')  # Blue border color
            pgBorders.append(border_el)
        sectPr.append(pgBorders)

@app.route('/upload', methods=['POST'])
@rate_limited
def upload_file():
    if 'file' not in request.files:
        return jsonify({'error': 'No file part'}), 400
    file = request.files['file']
    if file.filename == '':
        return jsonify({'error': 'No selected file'}), 400

    if file and file.filename.endswith('.pdf'):
        try:
            start_time = time.time()
            # Process PDF in small batches
            summary, total_pages = process_pdf_in_batches(file)
            processing_time = time.time() - start_time

            docx_buffer = create_word_document(summary)

            return jsonify({
                'docx': base64.b64encode(docx_buffer.getvalue()).decode('utf-8'),
                'total_pages': total_pages,
                'processing_time': round(processing_time, 2)
            })
        except Exception as e:
            return jsonify({'error': str(e)}), 500
    else:
        return jsonify({'error': 'Invalid file type. Please upload a PDF.'}), 400

# ... [Other route handlers remain unchanged] ...

if __name__ == '__main__':
    app.run(debug=True)
"