Made changes to Getting started with ALwrity and added lot of details on API keys
This commit is contained in:
157
lib/gpt_providers/text_generation/README.md
Normal file
157
lib/gpt_providers/text_generation/README.md
Normal file
@@ -0,0 +1,157 @@
|
||||
# AI Text Generation Guide for Content Creators
|
||||
|
||||
## What is AI Text Generation?
|
||||
|
||||
AI Text Generation is a powerful tool that helps content creators generate high-quality, engaging content using advanced artificial intelligence models. This tool supports multiple AI providers, each offering unique strengths for different types of content creation.
|
||||
|
||||
## Available AI Models
|
||||
|
||||
### 1. OpenAI's GPT Models
|
||||
**Best for:** General content creation, creative writing, and detailed analysis
|
||||
|
||||
**Key Features:**
|
||||
- **Advanced Understanding**: Deep comprehension of context and nuance
|
||||
- **Creative Flexibility**: Adapts to various writing styles and tones
|
||||
- **Consistent Quality**: Reliable output for long-form content
|
||||
- **Streaming Responses**: Real-time content generation
|
||||
|
||||
**Use Cases:**
|
||||
- Blog posts and articles
|
||||
- Creative storytelling
|
||||
- Technical writing
|
||||
- Content analysis and summaries
|
||||
|
||||
### 2. Google's Gemini Pro
|
||||
**Best for:** Balanced content creation and factual accuracy
|
||||
|
||||
**Key Features:**
|
||||
- **Factual Accuracy**: Strong focus on reliable information
|
||||
- **Balanced Output**: Good mix of creativity and precision
|
||||
- **Multilingual Support**: Works well across different languages
|
||||
- **Contextual Understanding**: Strong grasp of context
|
||||
|
||||
**Use Cases:**
|
||||
- Educational content
|
||||
- Fact-based articles
|
||||
- Multilingual content
|
||||
- Research-based writing
|
||||
|
||||
### 3. Anthropic's Claude
|
||||
**Best for:** Professional and academic content
|
||||
|
||||
**Key Features:**
|
||||
- **Professional Tone**: Excellent for formal writing
|
||||
- **Detailed Analysis**: Strong analytical capabilities
|
||||
- **Ethical Considerations**: Built-in ethical guidelines
|
||||
- **Long-form Excellence**: Great for extended content
|
||||
|
||||
**Use Cases:**
|
||||
- Academic writing
|
||||
- Professional documentation
|
||||
- Research papers
|
||||
- Policy documents
|
||||
|
||||
### 4. DeepSeek
|
||||
**Best for:** Technical and specialized content
|
||||
|
||||
**Key Features:**
|
||||
- **Technical Precision**: Excellent for technical writing
|
||||
- **Specialized Knowledge**: Strong in specific domains
|
||||
- **Efficient Processing**: Fast response times
|
||||
- **Customizable Output**: Flexible formatting options
|
||||
|
||||
**Use Cases:**
|
||||
- Technical documentation
|
||||
- Industry-specific content
|
||||
- Scientific writing
|
||||
- Specialized reports
|
||||
|
||||
## How to Use the Text Generation Tool
|
||||
|
||||
### 1. Setting Up Your Content Parameters
|
||||
Before generating content, you can specify:
|
||||
- **Language**: Choose your preferred writing language
|
||||
- **Tone**: Select the appropriate tone (formal, casual, technical, etc.)
|
||||
- **Content Length**: Set your desired word count
|
||||
- **Content Type**: Specify the type of content (blog, article, etc.)
|
||||
- **Target Audience**: Define your reader demographic
|
||||
- **Output Format**: Choose your preferred format (Markdown, HTML, etc.)
|
||||
|
||||
### 2. Content Generation Process
|
||||
1. **Input Your Requirements**: Provide your content specifications
|
||||
2. **Select Your Model**: Choose the AI model best suited for your needs
|
||||
3. **Generate Content**: Let the AI create your content
|
||||
4. **Review and Edit**: Polish the generated content as needed
|
||||
|
||||
### 3. Customization Options
|
||||
You can adjust various parameters to fine-tune your content:
|
||||
- **Temperature**: Control creativity (lower = more focused, higher = more creative)
|
||||
- **Maximum Length**: Set content length limits
|
||||
- **Output Format**: Choose how you want the content structured
|
||||
- **Language Style**: Adjust the writing style and complexity
|
||||
|
||||
## Best Practices for Content Creation
|
||||
|
||||
### 1. Before Generation
|
||||
- Clearly define your content goals
|
||||
- Identify your target audience
|
||||
- Choose the appropriate model for your needs
|
||||
- Set clear parameters for tone and style
|
||||
|
||||
### 2. During Generation
|
||||
- Monitor the content quality
|
||||
- Ensure it aligns with your brand voice
|
||||
- Check for factual accuracy
|
||||
- Maintain consistency with your style guide
|
||||
|
||||
### 3. After Generation
|
||||
- Review and edit the content
|
||||
- Fact-check important information
|
||||
- Optimize for SEO if needed
|
||||
- Add your personal touch
|
||||
|
||||
## Tips for Optimal Results
|
||||
|
||||
1. **Be Specific**: Provide clear instructions for the AI
|
||||
2. **Use Examples**: Share examples of your desired style
|
||||
3. **Iterate**: Don't hesitate to regenerate if needed
|
||||
4. **Review**: Always review and edit generated content
|
||||
5. **Optimize**: Fine-tune parameters for better results
|
||||
|
||||
## Common Use Cases
|
||||
|
||||
### Blog Writing
|
||||
- Generate engaging blog posts
|
||||
- Create consistent content series
|
||||
- Develop topic outlines
|
||||
- Write product reviews
|
||||
|
||||
### Article Creation
|
||||
- Research-based articles
|
||||
- Opinion pieces
|
||||
- How-to guides
|
||||
- Industry analysis
|
||||
|
||||
### Technical Writing
|
||||
- Documentation
|
||||
- User guides
|
||||
- Technical specifications
|
||||
- Process descriptions
|
||||
|
||||
### Creative Writing
|
||||
- Story development
|
||||
- Character creation
|
||||
- Plot outlines
|
||||
- Scene descriptions
|
||||
|
||||
## Need Help?
|
||||
|
||||
If you encounter any issues or need assistance:
|
||||
1. Check the model-specific documentation
|
||||
2. Review your input parameters
|
||||
3. Try adjusting the generation settings
|
||||
4. Contact support for technical issues
|
||||
|
||||
---
|
||||
|
||||
*Note: This tool is designed to assist content creators in generating high-quality content. While AI can help with content creation, it's important to review and edit the generated content to ensure it meets your standards and brand guidelines.*
|
||||
@@ -1,33 +1,121 @@
|
||||
import os
|
||||
|
||||
import anthropic
|
||||
from anthropic import Anthropic
|
||||
import streamlit as st
|
||||
import asyncio
|
||||
from tenacity import (
|
||||
retry,
|
||||
stop_after_attempt,
|
||||
wait_random_exponential,
|
||||
) # for exponential backoff
|
||||
|
||||
# Configure standard logging
|
||||
import logging
|
||||
logging.basicConfig(level=logging.INFO, format='[%(asctime)s-%(levelname)s-%(module)s-%(lineno)d]- %(message)s')
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
def anthropic_text_response(prompt):
|
||||
""" """
|
||||
client = Anthropic(api_key=os.environ.get("ANTHROPIC_API_KEY"),)
|
||||
|
||||
async def test_anthropic_api_key(api_key: str) -> tuple[bool, str]:
|
||||
"""
|
||||
Test if the provided Anthropic API key is valid.
|
||||
|
||||
Args:
|
||||
api_key (str): The Anthropic API key to test
|
||||
|
||||
Returns:
|
||||
tuple[bool, str]: A tuple containing (is_valid, message)
|
||||
"""
|
||||
try:
|
||||
# Create Anthropic client with the provided key
|
||||
client = anthropic.Anthropic(api_key=api_key)
|
||||
|
||||
# Try a simple completion as a test
|
||||
response = client.messages.create(
|
||||
max_tokens=1024,
|
||||
messages=[
|
||||
{
|
||||
"role": "user",
|
||||
"content": prompt,
|
||||
}
|
||||
],
|
||||
# This will come from config file.
|
||||
model="claude-3-opus-20240229",
|
||||
model="claude-3-haiku-20240307",
|
||||
max_tokens=10,
|
||||
messages=[{
|
||||
"role": "user",
|
||||
"content": "Say hello"
|
||||
}]
|
||||
)
|
||||
return(message.content)
|
||||
except anthropic.APIConnectionError as e:
|
||||
st.error("The server could not be reached")
|
||||
st.error(e.__cause__) # an underlying Exception, likely raised within httpx.
|
||||
except anthropic.RateLimitError as e:
|
||||
st.error("A 429 status code was received; we should back off a bit.")
|
||||
except anthropic.APIStatusError as e:
|
||||
st.error("Another non-200-range status code was received")
|
||||
st.error(e.status_code)
|
||||
st.error(e.response)
|
||||
|
||||
# If we get here, the key is valid
|
||||
return True, "Anthropic API key is valid"
|
||||
|
||||
except anthropic.AuthenticationError:
|
||||
return False, "Invalid Anthropic API key"
|
||||
except anthropic.RateLimitError:
|
||||
return False, "Rate limit exceeded. Please try again later."
|
||||
except Exception as e:
|
||||
return False, f"Error testing Anthropic API key: {str(e)}"
|
||||
|
||||
@retry(wait=wait_random_exponential(min=1, max=60), stop=stop_after_attempt(6))
|
||||
def anthropic_text_response(prompt, model="claude-3-haiku-20240307", temperature=0.7, max_tokens=2048, top_p=0.9, n=1, system_prompt="You are a helpful AI assistant."):
|
||||
"""
|
||||
Generate text using Anthropic's Claude model with retry logic.
|
||||
|
||||
Args:
|
||||
prompt (str): The input text to generate completion for
|
||||
model (str, optional): Model to use. Defaults to "claude-3-haiku-20240307"
|
||||
temperature (float, optional): Controls randomness. Defaults to 0.7
|
||||
max_tokens (int, optional): Maximum number of tokens to generate. Defaults to 2048
|
||||
top_p (float, optional): Controls diversity. Defaults to 0.9
|
||||
n (int, optional): Number of completions to generate. Defaults to 1
|
||||
system_prompt (str, optional): System prompt to guide the model. Defaults to "You are a helpful AI assistant."
|
||||
|
||||
Returns:
|
||||
str: The generated text completion
|
||||
"""
|
||||
try:
|
||||
# Create Anthropic client
|
||||
client = anthropic.Anthropic(api_key=os.getenv('ANTHROPIC_API_KEY'))
|
||||
|
||||
# Generate completion
|
||||
response = client.messages.create(
|
||||
model=model,
|
||||
max_tokens=max_tokens,
|
||||
temperature=temperature,
|
||||
messages=[
|
||||
{"role": "system", "content": system_prompt},
|
||||
{"role": "user", "content": prompt}
|
||||
]
|
||||
)
|
||||
|
||||
# Return the generated text
|
||||
return response.content[0].text
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error in Anthropic text generation: {e}")
|
||||
raise SystemExit from e
|
||||
|
||||
def anthropic_text_gen(prompt, model="claude-3-haiku-20240307", temperature=0.7, max_tokens=2048):
|
||||
"""
|
||||
Generate text using Anthropic's Claude model.
|
||||
|
||||
Args:
|
||||
prompt (str): The input text to generate completion for
|
||||
model (str, optional): Model to use. Defaults to "claude-3-haiku-20240307"
|
||||
temperature (float, optional): Controls randomness. Defaults to 0.7
|
||||
max_tokens (int, optional): Maximum number of tokens to generate. Defaults to 2048
|
||||
|
||||
Returns:
|
||||
str: The generated text completion
|
||||
"""
|
||||
try:
|
||||
# Create Anthropic client
|
||||
client = anthropic.Anthropic(api_key=os.getenv('ANTHROPIC_API_KEY'))
|
||||
|
||||
# Generate completion
|
||||
response = client.messages.create(
|
||||
model=model,
|
||||
max_tokens=max_tokens,
|
||||
temperature=temperature,
|
||||
messages=[{
|
||||
"role": "user",
|
||||
"content": prompt
|
||||
}]
|
||||
)
|
||||
|
||||
# Return the generated text
|
||||
return response.content[0].text
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error in Anthropic text generation: {e}")
|
||||
return str(e)
|
||||
|
||||
@@ -6,6 +6,8 @@ from tenacity import (
|
||||
stop_after_attempt,
|
||||
wait_random_exponential,
|
||||
)
|
||||
import openai
|
||||
import asyncio
|
||||
|
||||
# Configure standard logging
|
||||
logging.basicConfig(level=logging.INFO, format='[%(asctime)s-%(levelname)s-%(module)s-%(lineno)d]- %(message)s')
|
||||
@@ -67,3 +69,71 @@ def deepseek_text_response(prompt, model, temperature, max_tokens, top_p, n, sys
|
||||
except Exception as err:
|
||||
logger.error(f"DeepSeek error: {err}")
|
||||
raise SystemExit from err
|
||||
|
||||
async def test_deepseek_api_key(api_key: str) -> tuple[bool, str]:
|
||||
"""
|
||||
Test if the provided DeepSeek API key is valid.
|
||||
|
||||
Args:
|
||||
api_key (str): The DeepSeek API key to test
|
||||
|
||||
Returns:
|
||||
tuple[bool, str]: A tuple containing (is_valid, message)
|
||||
"""
|
||||
try:
|
||||
# Create OpenAI client with DeepSeek base URL
|
||||
client = openai.OpenAI(
|
||||
api_key=api_key,
|
||||
base_url="https://api.deepseek.com/v1"
|
||||
)
|
||||
|
||||
# Try to list models as a simple API test
|
||||
models = client.models.list()
|
||||
|
||||
# If we get here, the key is valid
|
||||
return True, "DeepSeek API key is valid"
|
||||
|
||||
except openai.AuthenticationError:
|
||||
return False, "Invalid DeepSeek API key"
|
||||
except openai.RateLimitError:
|
||||
return False, "Rate limit exceeded. Please try again later."
|
||||
except Exception as e:
|
||||
return False, f"Error testing DeepSeek API key: {str(e)}"
|
||||
|
||||
def deepseek_text_gen(prompt, model="deepseek-chat", temperature=0.7, max_tokens=2048):
|
||||
"""
|
||||
Generate text using DeepSeek's API.
|
||||
|
||||
Args:
|
||||
prompt (str): The input text to generate completion for
|
||||
model (str, optional): Model to use. Defaults to "deepseek-chat"
|
||||
temperature (float, optional): Controls randomness. Defaults to 0.7
|
||||
max_tokens (int, optional): Maximum number of tokens to generate. Defaults to 2048
|
||||
|
||||
Returns:
|
||||
str: The generated text completion
|
||||
"""
|
||||
try:
|
||||
# Create OpenAI client with DeepSeek base URL
|
||||
client = openai.OpenAI(
|
||||
api_key=os.getenv('DEEPSEEK_API_KEY'),
|
||||
base_url="https://api.deepseek.com/v1"
|
||||
)
|
||||
|
||||
# Generate chat completion
|
||||
response = client.chat.completions.create(
|
||||
model=model,
|
||||
messages=[{
|
||||
"role": "user",
|
||||
"content": prompt
|
||||
}],
|
||||
temperature=temperature,
|
||||
max_tokens=max_tokens
|
||||
)
|
||||
|
||||
# Return the generated text
|
||||
return response.choices[0].message.content
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error in DeepSeek text generation: {e}")
|
||||
return str(e)
|
||||
|
||||
@@ -18,6 +18,12 @@ from tenacity import (
|
||||
wait_random_exponential,
|
||||
)
|
||||
|
||||
import asyncio
|
||||
|
||||
# Configure standard logging
|
||||
import logging
|
||||
logging.basicConfig(level=logging.INFO, format='[%(asctime)s-%(levelname)s-%(module)s-%(lineno)d]- %(message)s')
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@retry(wait=wait_random_exponential(min=1, max=60), stop=stop_after_attempt(6))
|
||||
def gemini_text_response(prompt, temperature, top_p, n, max_tokens, system_prompt):
|
||||
@@ -96,3 +102,65 @@ def gemini_text_response(prompt, temperature, top_p, n, max_tokens, system_promp
|
||||
# return response.text
|
||||
# except Exception as err:
|
||||
# logger.error(f"Failed to get SEO METADATA from Gemini: {err}. Retrying.")
|
||||
|
||||
async def test_gemini_api_key(api_key: str) -> tuple[bool, str]:
|
||||
"""
|
||||
Test if the provided Gemini API key is valid.
|
||||
|
||||
Args:
|
||||
api_key (str): The Gemini API key to test
|
||||
|
||||
Returns:
|
||||
tuple[bool, str]: A tuple containing (is_valid, message)
|
||||
"""
|
||||
try:
|
||||
# Configure Gemini with the provided key
|
||||
genai.configure(api_key=api_key)
|
||||
|
||||
# Try to list models as a simple API test
|
||||
models = genai.list_models()
|
||||
|
||||
# Check if Gemini Pro is available
|
||||
if any(model.name == "gemini-pro" for model in models):
|
||||
return True, "Gemini API key is valid"
|
||||
else:
|
||||
return False, "Gemini Pro model not available with this API key"
|
||||
|
||||
except Exception as e:
|
||||
return False, f"Error testing Gemini API key: {str(e)}"
|
||||
|
||||
def gemini_pro_text_gen(prompt, temperature=0.7, top_p=0.9, top_k=40, max_tokens=2048):
|
||||
"""
|
||||
Generate text using Google's Gemini Pro model.
|
||||
|
||||
Args:
|
||||
prompt (str): The input text to generate completion for
|
||||
temperature (float, optional): Controls randomness. Defaults to 0.7
|
||||
top_p (float, optional): Controls diversity. Defaults to 0.9
|
||||
top_k (int, optional): Controls vocabulary size. Defaults to 40
|
||||
max_tokens (int, optional): Maximum number of tokens to generate. Defaults to 2048
|
||||
|
||||
Returns:
|
||||
str: The generated text completion
|
||||
"""
|
||||
try:
|
||||
# Configure the model
|
||||
model = genai.GenerativeModel('gemini-pro')
|
||||
|
||||
# Generate content
|
||||
response = model.generate_content(
|
||||
prompt,
|
||||
generation_config=genai.types.GenerationConfig(
|
||||
temperature=temperature,
|
||||
top_p=top_p,
|
||||
top_k=top_k,
|
||||
max_output_tokens=max_tokens,
|
||||
)
|
||||
)
|
||||
|
||||
# Return the generated text
|
||||
return response.text
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error in Gemini Pro text generation: {e}")
|
||||
return str(e)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import os
|
||||
import sys
|
||||
import configparser
|
||||
import json
|
||||
from pathlib import Path
|
||||
from dotenv import load_dotenv
|
||||
load_dotenv(Path('../.env'))
|
||||
@@ -28,10 +28,20 @@ def llm_text_gen(prompt):
|
||||
str: Generated text based on the prompt.
|
||||
"""
|
||||
try:
|
||||
# Read the config param to create system instruction for the LLM.
|
||||
gpt_provider, model, temperature, max_tokens, top_p, n, fp = read_return_config_section('llm_config')
|
||||
blog_tone, blog_demographic, blog_type, blog_language, \
|
||||
logger.info("[llm_text_gen] Starting text generation")
|
||||
logger.debug(f"[llm_text_gen] Prompt length: {len(prompt)} characters")
|
||||
|
||||
try:
|
||||
# Read the config param to create system instruction for the LLM.
|
||||
gpt_provider, model, temperature, max_tokens, top_p, n, fp = read_return_config_section('llm_config')
|
||||
blog_tone, blog_demographic, blog_type, blog_language, \
|
||||
blog_output_format, blog_length = read_return_config_section('blog_characteristics')
|
||||
|
||||
logger.debug(f"[llm_text_gen] Config loaded successfully - Provider: {gpt_provider}, Model: {model}")
|
||||
|
||||
except Exception as err:
|
||||
logger.error(f"[llm_text_gen] Error reading config params: {err}")
|
||||
raise err
|
||||
|
||||
# Construct the system prompt with the sidebar config params.
|
||||
system_instructions = f"""You are a highly skilled content writer with a knack for creating engaging and informative content.
|
||||
@@ -117,7 +127,6 @@ def check_gpt_provider(gpt_provider):
|
||||
return gpt_provider
|
||||
|
||||
|
||||
|
||||
def get_api_key(gpt_provider):
|
||||
"""
|
||||
Get the API key for the specified GPT provider.
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
import os
|
||||
import logging
|
||||
from pathlib import Path
|
||||
|
||||
from mistralai.client import MistralClient
|
||||
from mistralai.models.chat_completion import ChatMessage
|
||||
|
||||
logging.basicConfig(level=logging.INFO, format='%(asctime)s-%(levelname)s-%(module)s-%(lineno)d-%(message)s')
|
||||
from dotenv import load_dotenv
|
||||
load_dotenv(Path('../../.env'))
|
||||
from mistralai import Mistral
|
||||
import asyncio
|
||||
from loguru import logger
|
||||
|
||||
from tenacity import (
|
||||
retry,
|
||||
@@ -15,26 +11,134 @@ from tenacity import (
|
||||
wait_random_exponential,
|
||||
) # for exponential backoff
|
||||
|
||||
from dotenv import load_dotenv
|
||||
load_dotenv(Path('../../.env'))
|
||||
|
||||
# Configure standard logging
|
||||
logging.basicConfig(level=logging.INFO, format='[%(asctime)s-%(levelname)s-%(module)s-%(lineno)d]- %(message)s')
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
async def test_mistral_api_key(api_key: str) -> tuple[bool, str]:
|
||||
"""
|
||||
Test if the provided Mistral API key is valid.
|
||||
|
||||
Args:
|
||||
api_key (str): The Mistral API key to test
|
||||
|
||||
Returns:
|
||||
tuple[bool, str]: A tuple containing (is_valid, message)
|
||||
"""
|
||||
try:
|
||||
async with Mistral(api_key=api_key) as client:
|
||||
# Try a simple completion as a test
|
||||
response = await client.chat.complete_async(
|
||||
model="mistral-small-latest",
|
||||
messages=[{
|
||||
"role": "user",
|
||||
"content": "Hello"
|
||||
}],
|
||||
max_tokens=10
|
||||
)
|
||||
|
||||
if response and response.choices:
|
||||
return True, "Mistral API key is valid"
|
||||
else:
|
||||
return False, "Invalid response from Mistral API"
|
||||
|
||||
except Exception as e:
|
||||
return False, f"Error testing Mistral API key: {str(e)}"
|
||||
|
||||
@retry(wait=wait_random_exponential(min=1, max=60), stop=stop_after_attempt(6))
|
||||
def mistral_text_response(prompt):
|
||||
""" Common function to get text response from minstral. """
|
||||
api_key = os.environ["MISTRAL_API_KEY"]
|
||||
model = "mistral-medium"
|
||||
async def mistral_chat_completion_async(
|
||||
prompt: str,
|
||||
model: str = "mistral-small-latest",
|
||||
temperature: float = 0.7,
|
||||
max_tokens: int = 2048,
|
||||
top_p: float = 0.9,
|
||||
system_prompt: str = "You are a helpful AI assistant."
|
||||
) -> str:
|
||||
"""
|
||||
Generate text using Mistral's chat completion API asynchronously.
|
||||
|
||||
Args:
|
||||
prompt (str): The input text to generate completion for
|
||||
model (str, optional): Model to use. Defaults to "mistral-small-latest"
|
||||
temperature (float, optional): Controls randomness. Defaults to 0.7
|
||||
max_tokens (int, optional): Maximum number of tokens to generate. Defaults to 2048
|
||||
top_p (float, optional): Controls diversity. Defaults to 0.9
|
||||
system_prompt (str, optional): System prompt to guide the model. Defaults to "You are a helpful AI assistant."
|
||||
|
||||
Returns:
|
||||
str: The generated text completion
|
||||
"""
|
||||
try:
|
||||
async with Mistral(api_key=os.getenv('MISTRAL_API_KEY')) as client:
|
||||
messages = []
|
||||
|
||||
# Add system message if provided
|
||||
if system_prompt:
|
||||
messages.append({
|
||||
"role": "system",
|
||||
"content": system_prompt
|
||||
})
|
||||
|
||||
# Add user message
|
||||
messages.append({
|
||||
"role": "user",
|
||||
"content": prompt
|
||||
})
|
||||
|
||||
# Generate chat completion
|
||||
response = await client.chat.complete_async(
|
||||
model=model,
|
||||
messages=messages,
|
||||
temperature=temperature,
|
||||
max_tokens=max_tokens,
|
||||
top_p=top_p
|
||||
)
|
||||
|
||||
if response and response.choices:
|
||||
return response.choices[0].message.content
|
||||
else:
|
||||
raise Exception("No response generated")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error in Mistral chat completion: {e}")
|
||||
raise SystemExit from e
|
||||
|
||||
client = MistralClient(api_key=api_key)
|
||||
# Synchronous wrapper for compatibility
|
||||
def mistral_chat_completion(
|
||||
prompt: str,
|
||||
model: str = "mistral-small-latest",
|
||||
temperature: float = 0.7,
|
||||
max_tokens: int = 2048,
|
||||
top_p: float = 0.9,
|
||||
system_prompt: str = "You are a helpful AI assistant."
|
||||
) -> str:
|
||||
"""
|
||||
Synchronous wrapper for mistral_chat_completion_async.
|
||||
"""
|
||||
try:
|
||||
return asyncio.run(mistral_chat_completion_async(
|
||||
prompt=prompt,
|
||||
model=model,
|
||||
temperature=temperature,
|
||||
max_tokens=max_tokens,
|
||||
top_p=top_p,
|
||||
system_prompt=system_prompt
|
||||
))
|
||||
except Exception as e:
|
||||
logger.error(f"Error in Mistral chat completion: {e}")
|
||||
return str(e)
|
||||
|
||||
messages = [
|
||||
ChatMessage(role="user", content=prompt)
|
||||
]
|
||||
|
||||
# No streaming
|
||||
chat_response = client.chat(
|
||||
# For backward compatibility
|
||||
def mistral_text_response(prompt, model="mistral-small-latest", temperature=0.7, max_tokens=2048):
|
||||
"""
|
||||
Legacy function for backward compatibility.
|
||||
"""
|
||||
return mistral_chat_completion(
|
||||
prompt=prompt,
|
||||
model=model,
|
||||
messages=messages,
|
||||
temperature=temperature,
|
||||
max_tokens=max_tokens
|
||||
)
|
||||
print(chat_response)
|
||||
|
||||
# With streaming
|
||||
for chunk in client.chat_stream(model=model, messages=messages):
|
||||
print(chunk)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import os
|
||||
import time #IWish
|
||||
import openai
|
||||
import asyncio
|
||||
|
||||
# Configure standard logging
|
||||
import logging
|
||||
@@ -13,6 +14,33 @@ from tenacity import (
|
||||
) # for exponential backoff
|
||||
|
||||
|
||||
async def test_openai_api_key(api_key: str) -> tuple[bool, str]:
|
||||
"""
|
||||
Test if the provided OpenAI API key is valid.
|
||||
|
||||
Args:
|
||||
api_key (str): The OpenAI API key to test
|
||||
|
||||
Returns:
|
||||
tuple[bool, str]: A tuple containing (is_valid, message)
|
||||
"""
|
||||
try:
|
||||
# Create OpenAI client with the provided key
|
||||
client = openai.OpenAI(api_key=api_key)
|
||||
|
||||
# Try to list models as a simple API test
|
||||
models = client.models.list()
|
||||
|
||||
# If we get here, the key is valid
|
||||
return True, "OpenAI API key is valid"
|
||||
|
||||
except openai.AuthenticationError:
|
||||
return False, "Invalid OpenAI API key"
|
||||
except openai.RateLimitError:
|
||||
return False, "Rate limit exceeded. Please try again later."
|
||||
except Exception as e:
|
||||
return False, f"Error testing OpenAI API key: {str(e)}"
|
||||
|
||||
@retry(wait=wait_random_exponential(min=1, max=60), stop=stop_after_attempt(6))
|
||||
def openai_chatgpt(prompt, model, temperature, max_tokens, top_p, n, fp, system_prompt):
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user