Varshith1909
Mistake modified
813e1f5
import gradio as gr
import httpx
import json
import asyncio
import os
import sys
from dotenv import load_dotenv
from typing import List, Dict, Any
# MCP imports
try:
from mcp.server import Server
from mcp.server.stdio import stdio_server
from mcp.types import Tool, TextContent
MCP_AVAILABLE = True
except ImportError:
MCP_AVAILABLE = False
print("MCP not available. Install with: pip install mcp")
# Load environment variables
load_dotenv()
class ConversationTransfer:
def __init__(self):
self.anthropic_key = os.getenv("ANTHROPIC_API_KEY")
self.mistral_key = os.getenv("MISTRAL_API_KEY")
self.hyperbolic_key = os.getenv("HYPERBOLIC_API_KEY")
# Print status
print(f"πŸ”‘ API Keys Status:")
print(f" Anthropic: {'βœ…' if self.anthropic_key else '❌'}")
print(f" Mistral: {'βœ…' if self.mistral_key else '❌'}")
print(f" Hyperbolic: {'βœ…' if self.hyperbolic_key else '❌'}")
def parse_conversation(self, text: str) -> List[Dict]:
"""Parse conversation from various formats"""
try:
# Try JSON first
data = json.loads(text)
if isinstance(data, list):
return data
else:
return [data]
except json.JSONDecodeError:
# Parse plain text
return self._parse_plain_text(text)
def _parse_plain_text(self, text: str) -> List[Dict]:
"""Parse plain text conversation"""
messages = []
lines = text.strip().split('\n')
current_role = "user"
current_content = ""
for line in lines:
line = line.strip()
if not line:
continue
# Check for role indicators
if any(line.lower().startswith(prefix) for prefix in ['user:', 'human:', 'you:']):
if current_content:
messages.append({"role": current_role, "content": current_content.strip()})
current_role = "user"
current_content = line.split(':', 1)[1].strip() if ':' in line else line
elif any(line.lower().startswith(prefix) for prefix in ['assistant:', 'ai:', 'bot:', 'claude:', 'gpt:', 'chatgpt:']):
if current_content:
messages.append({"role": current_role, "content": current_content.strip()})
current_role = "assistant"
current_content = line.split(':', 1)[1].strip() if ':' in line else line
else:
current_content += " " + line
if current_content:
messages.append({"role": current_role, "content": current_content.strip()})
return messages
async def send_to_anthropic(self, messages: List[Dict]) -> str:
"""Send conversation to Anthropic Claude"""
if not self.anthropic_key:
return "❌ Anthropic API key not configured"
# Add transfer context
system_msg = "This conversation was transferred from another LLM. Please continue the conversation naturally, maintaining the same tone and context."
user_messages = [msg for msg in messages if msg["role"] != "system"]
headers = {
"x-api-key": self.anthropic_key,
"content-type": "application/json",
"anthropic-version": "2023-06-01"
}
payload = {
"model": "claude-3-haiku-20240307",
"max_tokens": 1000,
"system": system_msg,
"messages": user_messages
}
try:
async with httpx.AsyncClient(timeout=30.0) as client:
response = await client.post(
"https://api.anthropic.com/v1/messages",
headers=headers,
json=payload
)
response.raise_for_status()
result = response.json()
return result["content"][0]["text"]
except Exception as e:
return f"❌ Error calling Anthropic: {str(e)}"
async def send_to_mistral(self, messages: List[Dict]) -> str:
"""Send conversation to Mistral"""
if not self.mistral_key:
return "❌ Mistral API key not configured"
# Add transfer context
system_msg = {"role": "system", "content": "This conversation was transferred from another LLM. Please continue the conversation naturally."}
all_messages = [system_msg] + messages
headers = {
"Authorization": f"Bearer {self.mistral_key}",
"Content-Type": "application/json"
}
payload = {
"model": "mistral-small",
"messages": all_messages,
"max_tokens": 1000
}
try:
async with httpx.AsyncClient(timeout=30.0) as client:
response = await client.post(
"https://api.mistral.ai/v1/chat/completions",
headers=headers,
json=payload
)
response.raise_for_status()
result = response.json()
return result["choices"][0]["message"]["content"]
except Exception as e:
return f"❌ Error calling Mistral: {str(e)}"
async def send_to_hyperbolic(self, messages: List[Dict]) -> str:
"""Send conversation to Hyperbolic Labs"""
if not self.hyperbolic_key:
return "❌ Hyperbolic API key not configured"
# Add transfer context
system_msg = {"role": "system", "content": "This conversation was transferred from another LLM. Please continue naturally."}
all_messages = [system_msg] + messages
headers = {
"Authorization": f"Bearer {self.hyperbolic_key}",
"Content-Type": "application/json"
}
payload = {
"model": "meta-llama/Llama-2-7b-chat-hf",
"messages": all_messages,
"max_tokens": 1000
}
try:
async with httpx.AsyncClient(timeout=30.0) as client:
response = await client.post(
"https://api.hyperbolic.xyz/v1/chat/completions",
headers=headers,
json=payload
)
response.raise_for_status()
result = response.json()
return result["choices"][0]["message"]["content"]
except Exception as e:
return f"❌ Error calling Hyperbolic: {str(e)}"
async def transfer_conversation(self, history_text: str, source_provider: str, target_provider: str) -> str:
"""Main transfer function"""
if not history_text.strip():
return "❌ Please provide conversation history"
# Parse conversation
try:
messages = self.parse_conversation(history_text)
if not messages:
return "❌ Could not parse conversation history"
except Exception as e:
return f"❌ Error parsing conversation: {str(e)}"
# Build result
result = f"πŸ”„ **Transferring Conversation**\n"
result += f" From: {source_provider}\n"
result += f" To: {target_provider}\n"
result += f" Messages: {len(messages)}\n\n"
# Show parsed messages preview
if messages:
result += "πŸ“‹ **Conversation Preview:**\n"
for i, msg in enumerate(messages[:2]): # Show first 2 messages
content_preview = msg['content'][:100] + "..." if len(msg['content']) > 100 else msg['content']
result += f" {msg['role']}: {content_preview}\n"
if len(messages) > 2:
result += f" ... and {len(messages)-2} more messages\n"
result += "\n"
# Transfer to target provider
try:
if target_provider.lower() == "anthropic":
response = await self.send_to_anthropic(messages)
elif target_provider.lower() == "mistral":
response = await self.send_to_mistral(messages)
elif target_provider.lower() == "hyperbolic":
response = await self.send_to_hyperbolic(messages)
else:
return f"❌ Unsupported target provider: {target_provider}"
result += f"βœ… **Transfer Successful!**\n\n"
result += f"πŸ€– **Response from {target_provider.title()}:**\n"
result += f"{response}"
return result
except Exception as e:
return f"❌ Transfer failed: {str(e)}"
# Initialize the transfer tool
transfer_tool = ConversationTransfer()
# MCP Server Setup (if available)
if MCP_AVAILABLE:
server = Server("conversation-transfer")
@server.list_tools()
async def list_tools() -> List[Tool]:
return [
Tool(
name="transfer_conversation",
description="Transfer conversation history from one LLM provider to another",
inputSchema={
"type": "object",
"properties": {
"history_text": {
"type": "string",
"description": "Conversation history in JSON or plain text format"
},
"source_provider": {
"type": "string",
"description": "Source LLM provider (e.g., 'ChatGPT', 'Claude', 'Gemini')"
},
"target_provider": {
"type": "string",
"description": "Target LLM provider",
"enum": ["anthropic", "mistral", "hyperbolic"]
}
},
"required": ["history_text", "source_provider", "target_provider"]
}
)
]
@server.call_tool()
async def call_tool(name: str, arguments: Dict[str, Any]) -> List[TextContent]:
if name == "transfer_conversation":
result = await transfer_tool.transfer_conversation(
arguments["history_text"],
arguments["source_provider"],
arguments["target_provider"]
)
return [TextContent(type="text", text=result)]
else:
raise ValueError(f"Unknown tool: {name}")
def transfer_sync(history_text, source_provider, target_provider):
"""Synchronous wrapper for async function"""
return asyncio.run(transfer_tool.transfer_conversation(history_text, source_provider, target_provider))
# Create Gradio interface
def create_interface():
with gr.Blocks(title="LLM Conversation Transfer", theme=gr.themes.Default()) as interface:
gr.Markdown("# πŸ”„ LLM Conversation Transfer Tool")
gr.Markdown("**Seamlessly transfer conversations between different LLM providers!**")
with gr.Row():
with gr.Column(scale=2):
history_input = gr.Textbox(
label="πŸ“ Conversation History",
placeholder="""Paste your conversation here...
Examples:
β€’ Plain text: "User: Hello\nAssistant: Hi there!"
β€’ JSON: [{"role": "user", "content": "Hello"}]
β€’ ChatGPT export format""",
lines=10,
max_lines=25
)
with gr.Row():
source_dropdown = gr.Dropdown(
choices=["ChatGPT", "Claude", "Gemini", "Mistral", "Other"],
label="πŸ” Source Provider",
value="ChatGPT"
)
target_dropdown = gr.Dropdown(
choices=["anthropic", "mistral", "hyperbolic"],
label="🎯 Target Provider",
value="anthropic"
)
transfer_btn = gr.Button("πŸš€ Transfer Conversation", variant="primary", size="lg")
with gr.Column(scale=1):
gr.Markdown("### πŸ“– Quick Guide")
gr.Markdown("""
**1. Get Your Conversation**
- Copy from ChatGPT, Claude, etc.
- Export as JSON or plain text
**2. Paste & Select**
- Paste in the text box
- Choose source and target
**3. Transfer!**
- Click the button
- Get response from new LLM
### πŸ”§ Supported Providers
- βœ… **Anthropic** (Claude)
- βœ… **Mistral AI**
- βœ… **Hyperbolic Labs**
### πŸ“Š Status
""")
# API Status
status_text = "**API Keys:**\n"
status_text += f"- Anthropic: {'βœ…' if transfer_tool.anthropic_key else '❌'}\n"
status_text += f"- Mistral: {'βœ…' if transfer_tool.mistral_key else '❌'}\n"
status_text += f"- Hyperbolic: {'βœ…' if transfer_tool.hyperbolic_key else '❌'}\n"
status_text += f"- MCP Server: {'βœ…' if MCP_AVAILABLE else '❌'}"
gr.Markdown(status_text)
output = gr.Textbox(
label="πŸ“€ Transfer Result",
lines=12,
max_lines=25,
interactive=False
)
transfer_btn.click(
fn=transfer_sync,
inputs=[history_input, source_dropdown, target_dropdown],
outputs=output
)
# Add examples
with gr.Row():
gr.Examples(
examples=[
[
"User: What is Python programming?\nAssistant: Python is a high-level, interpreted programming language known for its simple syntax and readability. It's widely used in web development, data science, AI, and automation.",
"ChatGPT",
"anthropic"
],
[
'[{"role": "user", "content": "Explain quantum computing in simple terms"}, {"role": "assistant", "content": "Quantum computing uses quantum mechanical phenomena like superposition and entanglement to process information in ways that classical computers cannot."}]',
"Other",
"mistral"
],
[
"Human: Write a haiku about programming\nClaude: Code flows like water\nBugs hide in logic's shadows\nDebug brings the light",
"Claude",
"hyperbolic"
]
],
inputs=[history_input, source_dropdown, target_dropdown],
label="πŸ’‘ Try These Examples"
)
return interface
# Main execution
if __name__ == "__main__":
print("πŸš€ Starting LLM Conversation Transfer Tool...")
# Check if running as MCP server
if len(sys.argv) > 1 and sys.argv[1] == "mcp":
if MCP_AVAILABLE:
print("πŸ”§ Running as MCP Server...")
asyncio.run(stdio_server(server))
else:
print("❌ MCP not available. Install with: pip install mcp")
sys.exit(1)
else:
# Run Gradio interface
print("🌐 Starting Gradio Interface...")
interface = create_interface()
interface.launch(
share=False, # Disable share link
server_name="127.0.0.1", # Use localhost instead of 0.0.0.0
server_port=7860,
show_error=True,
inbrowser=True # Auto-open browser
)