Spaces:
Sleeping
Sleeping
| import json | |
| from typing import Generator, List | |
| import gradio as gr | |
| from openai import OpenAI | |
| from crop_utils import get_image_crop | |
| from prompts import ( | |
| get_chat_system_prompt, | |
| get_live_event_system_prompt, | |
| get_live_event_user_prompt, | |
| get_street_interview_prompt, | |
| get_street_interview_system_prompt, | |
| ) | |
| from transcript import TranscriptProcessor | |
| from utils import css, get_transcript_for_url, head | |
| from utils import openai_tools as tools | |
| from utils import setup_openai_key | |
| client = OpenAI() | |
| def get_initial_analysis( | |
| transcript_processor: TranscriptProcessor, cid, rsid, origin, ct, uid | |
| ) -> Generator[str, None, None]: | |
| """Perform initial analysis of the transcript using OpenAI.""" | |
| hardcoded_messages = { | |
| ( | |
| "9v3b-j426-kxxv_2024-11-19T204924", | |
| "2024-11-19T223131", | |
| ): f"""**Mala Ramakrishnan** | |
| 1. [Introduction and Event Overview <div id='topic' style="display: inline"> 40s at 03:25 </div>]({origin}/collab/{cid}/{rsid}?st={205}&et={240}&uid={uid}) | |
| 2. [Advice for Startup Founders <div id='topic' style="display: inline"> 30s at 26:10 </div>]({origin}/collab/{cid}/{rsid}?st={1570}&et={1600}&uid={uid}) | |
| **Raymond Lee** | |
| 1. [Event Introduction and Agenda <div id='topic' style="display: inline"> 120s at 00:39 </div>]({origin}/collab/{cid}/{rsid}?st={39}&et={159}&uid={uid}) | |
| 2. [Introduction of Mala Ramakrishnan <div id='topic' style="display: inline"> 20s at 02:51 </div>]({origin}/collab/{cid}/{rsid}?st={171}&et={191}&uid={uid}) | |
| **Vince Lane** | |
| 1. [Introduction and Background <div id='topic' style="display: inline"> 60s at 04:42 </div>]({origin}/collab/{cid}/{rsid}?st={282}&et={342}&uid={uid}) | |
| 2. [Advice for Founders <div id='topic' style="display: inline"> 60s at 19:48 </div>]({origin}/collab/{cid}/{rsid}?st={1188}&et={1248}&uid={uid}) | |
| **Marriott Wharton** | |
| 1. [Introduction and Investment Focus <div id='topic' style="display: inline"> 60s at 06:36 </div>]({origin}/collab/{cid}/{rsid}?st={396}&et={456}&uid={uid}) | |
| 2. [AI as a Fundamental Tool <div id='topic' style="display: inline"> 60s at 08:39 </div>]({origin}/collab/{cid}/{rsid}?st={519}&et={579}&uid={uid}) | |
| **spk_2** | |
| 1. [Introduction and Investment Focus <div id='topic' style="display: inline"> 60s at 05:56 </div>]({origin}/collab/{cid}/{rsid}?st={356}&et={416}&uid={uid}) | |
| 2. [Caution in AI Investments <div id='topic' style="display: inline"> 60s at 10:50 </div>]({origin}/collab/{cid}/{rsid}?st={650}&et={710}&uid={uid}) | |
| """, | |
| ( | |
| "9v3b-j426-kxxv_2024-11-19T204924", | |
| "2024-11-19T230912", | |
| ): f"""**Napoleon Paxton** | |
| 1. [Introduction and Background <div id='topic' style="display: inline"> 68s at 00:49 </div>](/collab/{cid}/{rsid}?st=49&et=117&uid={uid}) | |
| 2. [AI Squared's Business Model <div id='topic' style="display: inline"> 52s at 15:18 </div>](/collab/{cid}/{rsid}?st=918&et=970&uid={uid}) | |
| 3. [Federal Space and Networking <div id='topic' style="display: inline"> 88s at 24:35 </div>](/collab/{cid}/{rsid}?st=1475&et=1563&uid={uid}) | |
| **Lauren Hidalgo** | |
| 1. [Introduction and Experience <div id='topic' style="display: inline"> 77s at 03:01 </div>](/collab/{cid}/{rsid}?st=181&et=258&uid={uid}) | |
| 2. [AI Implementation Approach <div id='topic' style="display: inline"> 108s at 11:50 </div>](/collab/{cid}/{rsid}?st=710&et=818&uid={uid}) | |
| **Priti Padmanaban** | |
| 1. [Introduction and AI Marketing <div id='topic' style="display: inline"> 66s at 06:17 </div>](/collab/{cid}/{rsid}?st=377&et=443&uid={uid}) | |
| 2. [Responsible AI Framework <div id='topic' style="display: inline"> 109s at 08:15 </div>](/collab/{cid}/{rsid}?st=495&et=604&uid={uid}) | |
| 3. [AI in Climate Tech <div id='topic' style="display: inline"> 72s at 31:30 </div>](/collab/{cid}/{rsid}?st=1890&et=1962&uid={uid}) | |
| **Rishi Sawane** | |
| 1. [Introduction and Background <div id='topic' style="display: inline"> 98s at 04:17 </div>](/collab/{cid}/{rsid}?st=257&et=355&uid={uid}) | |
| 2. [AI and Recruitment Automation <div id='topic' style="display: inline"> 56s at 32:52 </div>](/collab/{cid}/{rsid}?st=1972&et=2028&uid={uid})""", | |
| ( | |
| "9v3b-j426-kxxv_2024-10-10T145749", | |
| "2024-10-10T160643", | |
| ): f"""**Mahesh** | |
| 1. [Zoom's AI Adoption Journey <div id='topic' style="display: inline"> 60s at 05:42 </div>](/collab/{cid}/{rsid}?st=342&et=402&uid={uid}) | |
| 2. [AI's Impact on Business Metrics <div id='topic' style="display: inline"> 60s at 07:49 </div>](/collab/{cid}/{rsid}?st=469&et=529&uid={uid}) | |
| 3. [AI's Role in Enterprise Adoption <div id='topic' style="display: inline"> 60s at 13:02 </div>](/collab/{cid}/{rsid}?st=782&et=842&uid={uid}) | |
| **Ben** | |
| 1. [AI in Enterprise Content Management <div id='topic' style="display: inline"> 60s at 04:18 </div>](/collab/{cid}/{rsid}?st=258&et=318&uid={uid}) | |
| 2. [Challenges in AI Adoption <div id='topic' style="display: inline"> 60s at 11:00 </div>](/collab/{cid}/{rsid}?st=660&et=720&uid={uid}) | |
| 3. [Trust and AI Implementation <div id='topic' style="display: inline"> 60s at 31:02 </div>](/collab/{cid}/{rsid}?st=1862&et=1922&uid={uid}) | |
| **Jennifer Lee** | |
| 1. [Introduction to Enterprise AI <div id='topic' style="display: inline"> 60s at 01:49 </div>](/collab/{cid}/{rsid}?st=109&et=169&uid={uid}) | |
| 2. [Investor's Perspective on AI <div id='topic' style="display: inline"> 60s at 17:18 </div>](/collab/{cid}/{rsid}?st=1038&et=1098&uid={uid}) | |
| 3. [Closing Remarks and Thanks <div id='topic' style="display: inline"> 60s at 58:57 </div>](/collab/{cid}/{rsid}?st=3537&et=3597&uid={uid}) | |
| **Robert** | |
| 1. [AI's Role in Customer Support <div id='topic' style="display: inline"> 60s at 08:34 </div>](/collab/{cid}/{rsid}?st=514&et=574&uid={uid}) | |
| 2. [Challenges in AI Implementation <div id='topic' style="display: inline"> 60s at 32:11 </div>](/collab/{cid}/{rsid}?st=1931&et=1991&uid={uid}) | |
| 3. [AI's Impact on Business Processes <div id='topic' style="display: inline"> 60s at 54:01 </div>](/collab/{cid}/{rsid}?st=3241&et=3301&uid={uid})""", | |
| ( | |
| "9v3b-j426-kxxv_2025-01-08T195932", | |
| "2025-01-08T201511", | |
| ): f"""**Paul Sutchman** | |
| 1. [Introduction and Purpose of the Panel <div id='topic' style="display: inline"> 46s at 00:11 </div>](/collab/{cid}/{rsid}?st=11&et=57&uid={uid}) | |
| 2. [Closing Remarks and Excitement for 2025 <div id='topic' style="display: inline"> 60s at 30:05 </div>](/collab/{cid}/{rsid}?st=1805&et=1865&uid={uid}) | |
| **Tomas** | |
| 1. [Introduction to Alembic Platform <div id='topic' style="display: inline"> 106s at 01:31 </div>](/collab/{cid}/{rsid}?st=91&et=197&uid={uid}) | |
| 2. [Challenges in Marketing Measurement <div id='topic' style="display: inline"> 84s at 15:15 </div>](/collab/{cid}/{rsid}?st=915&et=999&uid={uid}) | |
| 3. [Data Analysis and Customization <div id='topic' style="display: inline"> 112s at 23:16 </div>](/collab/{cid}/{rsid}?st=1396&et=1508&uid={uid}) | |
| **Jeffrey** | |
| 1. [Investment Perspective on Alembic <div id='topic' style="display: inline"> 130s at 03:37 </div>](/collab/{cid}/{rsid}?st=217&et=347&uid={uid}) | |
| 2. [Delta's Strategic Importance <div id='topic' style="display: inline"> 69s at 04:57 </div>](/collab/{cid}/{rsid}?st=297&et=366&uid={uid}) | |
| **Alicia** | |
| 1. [Importance of Measurement in Marketing <div id='topic' style="display: inline"> 120s at 09:36 </div>](/collab/{cid}/{rsid}?st=576&et=696&uid={uid}) | |
| 2. [Pilot with Alembic and Results <div id='topic' style="display: inline"> 120s at 12:10 </div>](/collab/{cid}/{rsid}?st=730&et=850&uid={uid}) | |
| 3. [Collaboration and Building Together <div id='topic' style="display: inline"> 120s at 27:13 </div>](/collab/{cid}/{rsid}?st=1633&et=1740&uid={uid})""", | |
| } | |
| if (cid, rsid) in hardcoded_messages: | |
| if "localhost" in origin: | |
| link_start = "http" | |
| else: | |
| link_start = "https" | |
| hardcoded_message = hardcoded_messages[(cid, rsid)] | |
| collected_message = "" | |
| chunks = [ | |
| hardcoded_message[i : i + 10] for i in range(0, len(hardcoded_message), 10) | |
| ] | |
| import time | |
| for chunk in chunks: | |
| collected_message += chunk | |
| yield collected_message | |
| time.sleep(0.05) | |
| return | |
| try: | |
| transcript = transcript_processor.get_transcript() | |
| speaker_mapping = transcript_processor.speaker_mapping | |
| client = OpenAI() | |
| if "localhost" in origin: | |
| link_start = "http" | |
| else: | |
| link_start = "https" | |
| if ct == "si": # street interview | |
| user_prompt = get_street_interview_prompt(transcript, uid, rsid, link_start) | |
| system_prompt = get_street_interview_system_prompt(cid, rsid, origin, ct) | |
| completion = client.chat.completions.create( | |
| model="gpt-4o", | |
| messages=[ | |
| {"role": "system", "content": system_prompt}, | |
| {"role": "user", "content": user_prompt}, | |
| ], | |
| stream=True, | |
| temperature=0.1, | |
| ) | |
| else: | |
| system_prompt = get_live_event_system_prompt( | |
| cid, rsid, origin, ct, speaker_mapping, transcript | |
| ) | |
| user_prompt = get_live_event_user_prompt(uid, link_start) | |
| completion = client.chat.completions.create( | |
| model="gpt-4o", | |
| messages=[ | |
| {"role": "system", "content": system_prompt}, | |
| {"role": "user", "content": user_prompt}, | |
| ], | |
| stream=True, | |
| temperature=0.1, | |
| ) | |
| collected_messages = [] | |
| # Iterate through the stream | |
| for chunk in completion: | |
| if chunk.choices[0].delta.content is not None: | |
| chunk_message = chunk.choices[0].delta.content | |
| collected_messages.append(chunk_message) | |
| # Yield the accumulated message so far | |
| yield "".join(collected_messages) | |
| except Exception as e: | |
| print(f"Error in initial analysis: {str(e)}") | |
| yield "An error occurred during initial analysis. Please check your API key and file path." | |
| def chat( | |
| message: str, | |
| chat_history: List, | |
| transcript_processor: TranscriptProcessor, | |
| cid, | |
| rsid, | |
| origin, | |
| ct, | |
| uid, | |
| ): | |
| try: | |
| client = OpenAI() | |
| if "localhost" in origin: | |
| link_start = "http" | |
| else: | |
| link_start = "https" | |
| speaker_mapping = transcript_processor.speaker_mapping | |
| system_prompt = get_chat_system_prompt( | |
| cid=cid, | |
| rsid=rsid, | |
| origin=origin, | |
| ct=ct, | |
| speaker_mapping=speaker_mapping, | |
| transcript=transcript_processor.get_transcript(), | |
| link_start=link_start, | |
| ) | |
| messages = [{"role": "system", "content": system_prompt}] | |
| for user_msg, assistant_msg in chat_history: | |
| if user_msg is not None: | |
| messages.append({"role": "user", "content": user_msg}) | |
| if assistant_msg is not None: | |
| messages.append({"role": "assistant", "content": assistant_msg}) | |
| # Add the current message | |
| messages.append({"role": "user", "content": message}) | |
| completion = client.chat.completions.create( | |
| model="gpt-4o", | |
| messages=messages, | |
| tools=tools, | |
| stream=True, | |
| temperature=0.3, | |
| ) | |
| collected_messages = [] | |
| tool_calls_detected = False | |
| for chunk in completion: | |
| if chunk.choices[0].delta.tool_calls: | |
| tool_calls_detected = True | |
| # Handle tool calls without streaming | |
| response = client.chat.completions.create( | |
| model="gpt-4o", | |
| messages=messages, | |
| tools=tools, | |
| ) | |
| if response.choices[0].message.tool_calls: | |
| tool_call = response.choices[0].message.tool_calls[0] | |
| if tool_call.function.name == "get_image": | |
| # Return the image directly in the chat | |
| image_data = get_image_crop(cid, rsid, uid, ct) | |
| print(response.choices[0].message) | |
| messages.append(response.choices[0].message) | |
| function_call_result_message = { | |
| "role": "tool", | |
| "content": "Here are the Image Crops", | |
| "name": tool_call.function.name, | |
| "tool_call_id": tool_call.id, | |
| } | |
| messages.append(function_call_result_message) | |
| yield image_data | |
| return | |
| if tool_call.function.name == "correct_speaker_name_with_url": | |
| args = eval(tool_call.function.arguments) | |
| url = args.get("url", None) | |
| if url: | |
| transcript_processor.correct_speaker_mapping_with_agenda( | |
| url | |
| ) | |
| corrected_speaker_mapping = ( | |
| transcript_processor.speaker_mapping | |
| ) | |
| messages.append(response.choices[0].message) | |
| function_call_result_message = { | |
| "role": "tool", | |
| "content": json.dumps( | |
| { | |
| "speaker_mapping": f"Corrected Speaker Mapping... {corrected_speaker_mapping}" | |
| } | |
| ), | |
| "name": tool_call.function.name, | |
| "tool_call_id": tool_call.id, | |
| } | |
| messages.append(function_call_result_message) | |
| # Get final response after tool call | |
| final_response = client.chat.completions.create( | |
| model="gpt-4o", | |
| messages=messages, | |
| stream=True, | |
| ) | |
| collected_chunk = "" | |
| for final_chunk in final_response: | |
| if final_chunk.choices[0].delta.content: | |
| collected_chunk += final_chunk.choices[ | |
| 0 | |
| ].delta.content | |
| yield collected_chunk | |
| return | |
| else: | |
| function_call_result_message = { | |
| "role": "tool", | |
| "content": "No URL Provided", | |
| "name": tool_call.function.name, | |
| "tool_call_id": tool_call.id, | |
| } | |
| elif tool_call.function.name == "correct_call_type": | |
| args = eval(tool_call.function.arguments) | |
| call_type = args.get("call_type", None) | |
| if call_type: | |
| # Stream the analysis for corrected call type | |
| for content in get_initial_analysis( | |
| transcript_processor, | |
| call_type, | |
| rsid, | |
| origin, | |
| call_type, | |
| uid, | |
| ): | |
| yield content | |
| return | |
| break # Exit streaming loop if tool calls detected | |
| if not tool_calls_detected and chunk.choices[0].delta.content is not None: | |
| chunk_message = chunk.choices[0].delta.content | |
| collected_messages.append(chunk_message) | |
| yield "".join(collected_messages) | |
| except Exception as e: | |
| print(f"Unexpected error in chat: {str(e)}") | |
| import traceback | |
| print(f"Traceback: {traceback.format_exc()}") | |
| yield "Sorry, there was an error processing your request." | |
| def create_chat_interface(): | |
| """Create and configure the chat interface.""" | |
| with gr.Blocks( | |
| fill_height=True, | |
| fill_width=True, | |
| css=css, | |
| head=head, | |
| theme=gr.themes.Default( | |
| font=[gr.themes.GoogleFont("Inconsolata"), "Arial", "sans-serif"] | |
| ), | |
| ) as demo: | |
| chatbot = gr.Chatbot( | |
| elem_id="chatbot_box", | |
| layout="bubble", | |
| show_label=False, | |
| show_share_button=False, | |
| show_copy_all_button=False, | |
| show_copy_button=False, | |
| render=True, | |
| ) | |
| msg = gr.Textbox(elem_id="chatbot_textbox", show_label=False) | |
| transcript_processor_state = gr.State() # maintain state of imp things | |
| call_id_state = gr.State() | |
| colab_id_state = gr.State() | |
| origin_state = gr.State() | |
| ct_state = gr.State() | |
| turl_state = gr.State() | |
| uid_state = gr.State() | |
| iframe_html = "<iframe id='link-frame'></iframe>" | |
| gr.HTML(value=iframe_html) # Add iframe to the UI | |
| def respond( | |
| message: str, | |
| chat_history: List, | |
| transcript_processor, | |
| cid, | |
| rsid, | |
| origin, | |
| ct, | |
| uid, | |
| ): | |
| if not transcript_processor: | |
| bot_message = "Transcript processor not initialized." | |
| chat_history.append((message, bot_message)) | |
| return "", chat_history | |
| chat_history.append((message, "")) | |
| for chunk in chat( | |
| message, | |
| chat_history[:-1], # Exclude the current incomplete message | |
| transcript_processor, | |
| cid, | |
| rsid, | |
| origin, | |
| ct, | |
| uid, | |
| ): | |
| chat_history[-1] = (message, chunk) | |
| yield "", chat_history | |
| msg.submit( | |
| respond, | |
| [ | |
| msg, | |
| chatbot, | |
| transcript_processor_state, | |
| call_id_state, | |
| colab_id_state, | |
| origin_state, | |
| ct_state, | |
| uid_state, | |
| ], | |
| [msg, chatbot], | |
| ) | |
| # Handle initial loading with streaming | |
| def on_app_load(request: gr.Request): | |
| turls = None | |
| cid = request.query_params.get("cid", None) | |
| rsid = request.query_params.get("rsid", None) | |
| origin = request.query_params.get("origin", None) | |
| ct = request.query_params.get("ct", None) | |
| turl = request.query_params.get("turl", None) | |
| uid = request.query_params.get("uid", None) | |
| pnames = request.query_params.get("pnames", None) | |
| required_params = ["cid", "rsid", "origin", "ct", "turl", "uid"] | |
| missing_params = [ | |
| param | |
| for param in required_params | |
| if request.query_params.get(param) is None | |
| ] | |
| if missing_params: | |
| error_message = ( | |
| f"Missing required parameters: {', '.join(missing_params)}" | |
| ) | |
| chatbot_value = [(None, error_message)] | |
| return [chatbot_value, None, None, None, None, None, None, None] | |
| if ct == "rp": | |
| # split turls based on , | |
| turls = turl.split(",") | |
| pnames = [pname.replace("_", " ") for pname in pnames.split(",")] | |
| try: | |
| if turls: | |
| transcript_data = [] | |
| for turl in turls: | |
| print("Getting Transcript for URL") | |
| transcript_data.append(get_transcript_for_url(turl)) | |
| print("Now creating Processor") | |
| transcript_processor = TranscriptProcessor( | |
| transcript_data=transcript_data, | |
| call_type=ct, | |
| person_names=pnames, | |
| ) | |
| else: | |
| transcript_data = get_transcript_for_url(turl) | |
| transcript_processor = TranscriptProcessor( | |
| transcript_data=transcript_data, call_type=ct | |
| ) | |
| # Initialize with empty message | |
| chatbot_value = [(None, "")] | |
| # Return initial values with the transcript processor | |
| return [ | |
| chatbot_value, | |
| transcript_processor, | |
| cid, | |
| rsid, | |
| origin, | |
| ct, | |
| turl, | |
| uid, | |
| ] | |
| except Exception as e: | |
| print(e) | |
| error_message = f"Error processing call_id {cid}: {str(e)}" | |
| chatbot_value = [(None, error_message)] | |
| return [chatbot_value, None, None, None, None, None, None, None] | |
| def display_processing_message(chatbot_value): | |
| """Display the processing message while maintaining state.""" | |
| # Create new chatbot value with processing message | |
| new_chatbot_value = [ | |
| (None, "Video is being processed. Please wait for the results...") | |
| ] | |
| # Return all states to maintain them | |
| return new_chatbot_value | |
| def stream_initial_analysis( | |
| chatbot_value, transcript_processor, cid, rsid, origin, ct, uid | |
| ): | |
| if not transcript_processor: | |
| return chatbot_value | |
| try: | |
| for chunk in get_initial_analysis( | |
| transcript_processor, cid, rsid, origin, ct, uid | |
| ): | |
| # Update the existing message instead of creating a new one | |
| chatbot_value[0] = (None, chunk) | |
| yield chatbot_value | |
| except Exception as e: | |
| chatbot_value[0] = (None, f"Error during analysis: {str(e)}") | |
| yield chatbot_value | |
| demo.load( | |
| on_app_load, | |
| inputs=None, | |
| outputs=[ | |
| chatbot, | |
| transcript_processor_state, | |
| call_id_state, | |
| colab_id_state, | |
| origin_state, | |
| ct_state, | |
| turl_state, | |
| uid_state, | |
| ], | |
| ).then( | |
| display_processing_message, | |
| inputs=[chatbot], | |
| outputs=[chatbot], | |
| ).then( | |
| stream_initial_analysis, | |
| inputs=[ | |
| chatbot, | |
| transcript_processor_state, | |
| call_id_state, | |
| colab_id_state, | |
| origin_state, | |
| ct_state, | |
| uid_state, | |
| ], | |
| outputs=[chatbot], | |
| ) | |
| return demo | |
| def main(): | |
| """Main function to run the application.""" | |
| try: | |
| setup_openai_key() | |
| demo = create_chat_interface() | |
| demo.launch(share=True) | |
| except Exception as e: | |
| print(f"Error starting application: {str(e)}") | |
| raise | |
| if __name__ == "__main__": | |
| main() | |