Spaces:
Running
Running
File size: 4,752 Bytes
1b8d07e a0a02f2 1b8d07e a0a02f2 1b8d07e a0a02f2 1b8d07e f1e41b8 1b8d07e 1e922dc 1b8d07e 013d287 1b8d07e 013d287 1b8d07e a0a02f2 1b8d07e a0a02f2 013d287 a0a02f2 013d287 1b8d07e a0a02f2 013d287 1b8d07e |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
import os
import json
from huggingface_hub import InferenceClient
class ProposalGenerator:
def __init__(self):
self.token = os.environ.get("HF_TOKEN")
# Client par défaut
self.client = InferenceClient(token=self.token)
def generate_from_description(self, project_name: str, description: str, model: str = "Qwen/Qwen2.5-Coder-32B-Instruct", provider: str = None):
"""
Generates a code and configuration proposal from a description.
Uses chat_completion for better compatibility.
"""
# Dynamic client configuration if necessary (e.g. provider change)
# Note: InferenceClient is lightweight, we can instantiate it on demand or use the existing one
# If provider is specified, use it. Otherwise let HF choose.
# "None" string from UI should be converted to None type
if provider == "None" or provider == "":
provider = None
print(f"🤖 LLM Call with Model: {model}, Provider: {provider}")
# Use current environment variable if available (supports UI updates), otherwise fallback to init token
current_token = os.environ.get("HF_TOKEN", self.token)
client = InferenceClient(model=model, token=current_token, provider=provider)
# print(self.token) # Avoid printing token in logs
messages = [
{
"role": "system",
"content": """You are an expert Python developer creating a tool for an MCP server via Gradio.
Your goal is to generate production-ready Python code that is fully typed and documented.
You MUST return ONLY a valid JSON object."""
},
{
"role": "user",
"content": f"""Create a tool named '{project_name}' that does the following: {description}
Requirements:
1. The function MUST have a clear and descriptive docstring (Google style preferred) explaining what it does, its arguments, and its return value. This docstring will be used as the tool description for the LLM.
2. The function arguments MUST be fully typed (e.g. `word: str`, `count: int`).
3. The function return type MUST be specified (e.g. `-> str`).
4. The function name should match '{project_name}' (normalized to python snake_case).
5. If the code requires external libraries (like `requests`, `pandas`, `numpy`), list them.
6. If the function calls an external API that needs a token, handle the token as an argument and precise it in the docstring.
Return ONLY a valid JSON object with the following structure:
{{
"python_code": "def function_name(arg1: type) -> type:\\n \\"\\"\\"Docstring here...\\"\\"\\"\\n ...",
"inputs": {{ "arg1": "Description for UI label" }},
"output_desc": "Description for UI label of the output",
"output_component": "text", # Choose from: text, image, audio, video, json, html, file
"requirements": ["requests", "pandas"]
}}
Make sure the python_code is a valid, complete, standalone Python function with all necessary imports inside (e.g. `import requests` inside the function or at top level if compatible).
If the user provides an API Specification (Swagger/OpenAPI), generate a client function that implements the main operation described.
Do not use markdown formatting (no ```json). Just the raw JSON string.
"""
}
]
try:
response = client.chat_completion(
messages,
max_tokens=4096, # Augmenté pour éviter la troncature
temperature=0.2,
stream=False
)
# Content extraction
content = response.choices[0].message.content.strip()
# Robust JSON extraction via Regex
import re
# Finds the first { and the last }
match = re.search(r'\{.*\}', content, re.DOTALL)
if match:
json_content = match.group(0)
return json.loads(json_content)
# Fallback: direct parsing attempt if regex fails (e.g. list or other format)
return json.loads(content)
except Exception as e:
print(f"Error generating proposal: {e}")
import traceback
traceback.print_exc()
# Fallback en cas d'erreur
return {
"python_code": f"# Error generating code: {str(e)}\n# Try changing the Inference Provider or Model.\ndef {project_name.replace('-', '_')}():\n return 'Error'",
"inputs": {},
"output_desc": "Error fallback"
}
# Singleton
proposal_generator = ProposalGenerator()
|