Spaces:
Sleeping
Sleeping
| # grad_bot2.py | |
| import sys | |
| import logging | |
| # 1) Configure logging to go to stdout | |
| logging.basicConfig( | |
| level=logging.INFO, | |
| stream=sys.stdout, | |
| format="%(asctime)s %(levelname)s %(name)s | %(message)s", | |
| ) | |
| # 2) (optional) Redirect built-in print → logging.info | |
| import builtins | |
| _original_print = builtins.print | |
| def _patched_print(*args, **kwargs): | |
| msg = " ".join(str(a) for a in args) | |
| logging.info(msg) | |
| builtins.print = _patched_print | |
| import gradio as gr | |
| import aiohttp | |
| import builtins | |
| # Configure logging to capture all stdout and stderr | |
| debug_format = '%(asctime)s - %(levelname)s - %(message)s' | |
| logging.basicConfig(stream=sys.stdout, level=logging.INFO, format=debug_format) | |
| # Redirect other loggers (uvicorn, gradio internal) to our root logger | |
| for logger_name in ['uvicorn', 'uvicorn.error', 'uvicorn.access', 'fastapi', 'gradio']: | |
| logger = logging.getLogger(logger_name) | |
| logger.handlers = logging.getLogger().handlers | |
| logger.propagate = True | |
| # Redirect stdout and stderr to logging | |
| class LoggerWriter: | |
| def __init__(self, level_func): | |
| self.level_func = level_func | |
| def write(self, message): | |
| message = message.strip() | |
| if message: | |
| self.level_func(message) | |
| def flush(self): | |
| pass | |
| sys.stdout = LoggerWriter(logging.info) | |
| sys.stderr = LoggerWriter(logging.error) | |
| # Also capture any print calls into logging | |
| _orig_print = builtins.print | |
| builtins.print = lambda *args, **kwargs: logging.info(' '.join(str(a) for a in args)) | |
| # Configuration for the licensing service | |
| LICENSING_SERVICE_BASE = 'https://gbdlicensing01containerapp.delightfulocean-00db0bf9.westeurope.azurecontainerapps.io' | |
| async def call_licensing_api( | |
| endpoint: str, | |
| index_name: str, | |
| api_key: str, | |
| input_text: str = None, | |
| question: str = None, | |
| ) -> dict: | |
| """ | |
| Sends a POST to either /create_index or /answer_question on your FastAPI service. | |
| """ | |
| if endpoint not in ("create_index", "answer_question"): | |
| raise ValueError("`endpoint` must be either 'create_index' or 'answer_question'") | |
| if endpoint == "create_index" and input_text is None: | |
| raise ValueError("When calling 'create_index', you must provide `input_text`") | |
| if endpoint == "answer_question" and question is None: | |
| raise ValueError("When calling 'answer_question', you must provide `question`") | |
| headers = {"X-API-Key": api_key, "Content-Type": "application/json"} | |
| payload = {"index_name": index_name} | |
| if endpoint == "create_index": | |
| payload["input_text"] = input_text | |
| else: | |
| payload["question"] = question | |
| timeout = aiohttp.ClientTimeout(total=60) | |
| async with aiohttp.ClientSession(timeout=timeout) as session: | |
| url = f"{LICENSING_SERVICE_BASE}/{endpoint}" | |
| logging.info(f"Calling licensing API at {url} with payload: {payload}") | |
| async with session.post(url, json=payload, headers=headers) as resp: | |
| resp.raise_for_status() | |
| result = await resp.json() | |
| logging.info(f"Received response: {result}") | |
| return result | |
| async def get_answer(api_key: str, final_selection: str, question: str) -> str: | |
| """Fetches an answer for the question based on the final topic selection.""" | |
| index_map = { | |
| 'Office 365': 'licensing-fundamentals' | |
| } | |
| index_name = index_map.get(final_selection) | |
| logging.info(f"Final selection: {final_selection} -> index: {index_name}") | |
| response = await call_licensing_api( | |
| endpoint="answer_question", | |
| index_name=index_name, | |
| api_key=api_key, | |
| question=question | |
| ) | |
| answer = response.get('answer', '') | |
| logging.info(f"Extracted answer: {answer}") | |
| return answer | |
| def main(): | |
| with gr.Blocks() as demo: | |
| # API key input | |
| api_key_input = gr.Textbox( | |
| label='Licensing Service API Key', | |
| placeholder='Paste your API key here', | |
| type='password' | |
| ) | |
| # Step 1: Primary topic selection | |
| primary_topic = gr.Radio( | |
| choices=['License Program', 'Products', 'Customer info'], | |
| label='What would you like to learn about?' | |
| ) | |
| # Step 2: Product type, shown only if 'Products' selected | |
| product_container = gr.Column(visible=False) | |
| with product_container: | |
| product_type = gr.Radio( | |
| choices=['Software', 'Online services'], | |
| label='Which products?' | |
| ) | |
| # Step 3: Service type, shown only if 'Online services' selected | |
| service_container = gr.Column(visible=False) | |
| with service_container: | |
| service_type = gr.Radio( | |
| choices=['Office 365'], | |
| label='Select an online service' | |
| ) | |
| # Step 4: QA, shown only after service_type selection | |
| qa_container = gr.Column(visible=False) | |
| with qa_container: | |
| question = gr.Textbox( | |
| lines=3, | |
| placeholder='Type your question here...', | |
| label='Your Question' | |
| ) | |
| answer = gr.Textbox( | |
| lines=5, | |
| interactive=False, | |
| label='Answer' | |
| ) | |
| submit = gr.Button('Submit') | |
| submit.click( | |
| fn=get_answer, | |
| inputs=[api_key_input, service_type, question], | |
| outputs=[answer] | |
| ) | |
| # Callbacks to reveal steps | |
| primary_topic.change( | |
| fn=lambda sel: gr.update(visible=(sel=='Products')), | |
| inputs=[primary_topic], | |
| outputs=[product_container] | |
| ) | |
| primary_topic.change( | |
| fn=lambda sel: gr.update(visible=False), | |
| inputs=[primary_topic], | |
| outputs=[service_container, qa_container] | |
| ) | |
| product_type.change( | |
| fn=lambda sel: gr.update(visible=(sel=='Online services')), | |
| inputs=[product_type], | |
| outputs=[service_container] | |
| ) | |
| product_type.change( | |
| fn=lambda sel: gr.update(visible=False), | |
| inputs=[product_type], | |
| outputs=[qa_container] | |
| ) | |
| service_type.change( | |
| fn=lambda sel: gr.update(visible=(sel=='Office 365')), | |
| inputs=[service_type], | |
| outputs=[qa_container] | |
| ) | |
| # Launch with public sharing enabled | |
| demo.launch(share=True) | |
| if __name__ == '__main__': | |
| main() | |