iTranslated by AI
The content below is an AI-generated translation. This is an experimental feature, and may contain errors. View original article
👌
Automating Replies to Managed Redmine with Azure OpenAI Service
TL;DR
- It is difficult to install plugins in managed Redmine services (e.g., Lychee Redmine).
- Since an API is provided, we can integrate it with OpenAI by running it periodically from services like Azure Functions.
- I've created a sample implementation as a starting point, making extensive use of ChatGPT.
Implementation Example
The conditions for triggering OpenAI are as follows:
- Target only issues created within the last 3 days.
- Target only issues that do not have any comments.
import requests
from datetime import datetime, timedelta
import os
import json
REDMINE_URL = os.environ.get('REDMINE_URL')
API_KEY = os.environ.get('API_KEY')
PROJECT_ID = os.environ.get('PROJECT_ID')
AZURE_OPENAI_URL = os.environ.get('AZURE_OPENAI_URL') # URL for Azure OpenAI Service
AZURE_OPENAI_KEY = os.environ.get('AZURE_OPENAI_KEY') # API key for Azure OpenAI Service
AZURE_OPENAI_SYSTEM_PROMPT = os.environ.get('AZURE_OPENAI_SYSTEM_PROMPT')
def get_recent_issues():
one_day_ago = (datetime.now() - timedelta(days=3)).strftime("%Y-%m-%d")
endpoint = f"{REDMINE_URL}/issues.json"
params = {
"key": API_KEY,
"created_on": f">={one_day_ago}T00:00:00Z",
"project_id": PROJECT_ID
}
response = requests.get(endpoint, params=params)
response.raise_for_status()
# Output for debugging
print("=== DEBUG: Recent Issues Response JSON ===")
print(json.dumps(response.json(), indent=4))
print("==========================================")
issues = response.json().get('issues', [])
return issues
def get_issue_details(issue_id):
endpoint = f"{REDMINE_URL}/issues/{issue_id}.json"
params = {
"key": API_KEY,
"include": "journals"
}
response = requests.get(endpoint, params=params)
response.raise_for_status()
# Output for debugging
print(f"=== DEBUG: Details for Issue {issue_id} Response JSON ===")
print(json.dumps(response.json(), indent=4))
print("=======================================================")
return response.json().get('issue', {})
def add_comment_to_issue(issue_id, comment):
"""
Function to add a comment to a Redmine issue
"""
endpoint = f"{REDMINE_URL}/issues/{issue_id}.json"
headers = {
"Content-Type": "application/json",
"X-Redmine-API-Key": API_KEY
}
data = {
"issue": {
"notes": comment
}
}
response = requests.put(endpoint, headers=headers, json=data)
response.raise_for_status()
def ask_openai(question):
headers = {
"Content-Type": "application/json",
"api-key": AZURE_OPENAI_KEY
}
data = {
"messages": [{"role": "system", "content": AZURE_OPENAI_SYSTEM_PROMPT},
{"role": "user", "content": question}],
"max_tokens": 800,
"temperature": 0.7,
"frequency_penalty": 0,
"presence_penalty": 0,
"top_p": 0.95,
"stop": None
}
response = requests.post(f"https://{AZURE_OPENAI_URL}/openai/deployments/gpt-35-turbo/chat/completions?api-version=2023-07-01-preview", headers=headers, json=data)
response.raise_for_status()
return response.json().get("choices", [{}])[0].get("message", {}).get("content", "").strip()
if __name__ == "__main__":
recent_issues = get_recent_issues()
for issue in recent_issues:
issue_details = get_issue_details(issue['id'])
journals = issue_details.get('journals', [])
# Display only issues that do not have any comments
if not journals:
print(f"ID: {issue_details['id']}, Subject: {issue_details['subject']}, Created on: {issue_details['created_on']}")
print("No comments or interactions.")
# Query Azure OpenAI Service
question = f"Can you provide insights on this issue? Think in English and answer in Japanese - 'Subject: {issue_details['subject']}\nDescription: {issue_details.get('description', 'No description provided.')}'"
openai_response = ask_openai(question)
# Debug output
print("=== Azure OpenAI Response ===")
print(openai_response)
print("==============================")
# Add OpenAI's response as a comment to the Redmine issue
add_comment_to_issue(issue_details['id'], openai_response)
print("-" * 50)
References
- REST API
- Rest Issues - Redmine
- Automatically replying using Azure OpenAI Service when an issue is created in Redmine
Discussion