Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified backend/app/services/nlg/__pycache__/nlg_engine.cpython-313.pyc
Binary file not shown.
Binary file not shown.
35 changes: 35 additions & 0 deletions backend/app/services/nlg/nlg_engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,3 +127,38 @@ async def generate_sentiment_text(self, raw_data: Dict[str, Any]) -> str:
error_msg="Failed to generate social sentiment summary due to an internal error. Please try again later."
)

async def generate_code_audit_text(self, code_data: Dict[str, Any], audit_data: Dict[str, Any]) -> str:
"""
Generates a comprehensive code audit summary using LLM prompts.
Includes clarity points, risk highlights, code activity, and repository quality indicators.
Handles missing audit information gracefully.
"""
if not code_data and not audit_data:
return self._format_output({
"section_id": "code_audit_summary",
"text": "Code audit and repository data are not available at this time. Please check back later for updates."
})

# Combine data for the prompt, handling potentially missing parts
combined_data = {
"code_data": json.dumps(code_data, indent=2) if code_data else "N/A",
"audit_data": json.dumps(audit_data, indent=2) if audit_data else "N/A",
}

template = get_template("code_audit_summary")
prompt = fill_template(template, **combined_data)

async with LLMClient() as llm_client:
try:
response = await llm_client.generate_text(prompt)
generated_text = response.get("choices", [{}])[0].get("message", {}).get("content", "").strip()
if not generated_text:
raise ValueError("LLM returned empty content for code_audit_summary.")
return self._format_output({"section_id": "code_audit_summary", "text": generated_text})
except Exception as e:
logger.error(f"Error generating code_audit_summary text with LLM: {e}", exc_info=True)
return self._format_output({
"section_id": "code_audit_summary",
"text": "Failed to generate code audit summary due to an internal error. Please try again later."
})

21 changes: 21 additions & 0 deletions backend/app/services/nlg/prompt_templates.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,27 @@ def get_template(section_id: str) -> str:
Risk Factors Data:
{data}
""",
"code_audit_summary": """
Based on the provided code audit and repository data, generate a comprehensive audit summary.
The summary should include:
1. **Clarity Points**: Highlight aspects of the codebase that are well-structured,
easy to understand, and follow best practices.
2. **Risk Highlights**: Identify potential security vulnerabilities, performance bottlenecks,
or maintainability issues.
3. **Code Activity**: Summarize recent development activity, such as commit frequency,
contributor engagement, and major feature implementations.
4. **Repository Quality Indicators**: Comment on aspects like test coverage,
documentation quality, and adherence to coding standards.

Handle cases where specific audit information might be missing by stating
that the information is not available or could not be assessed.

Code Audit Data:
{code_data}

Audit Data:
{audit_data}
""",
"team_roles_summary": """
Based on the following team member data, summarize the key roles and responsibilities
identified within the team. Highlight the diversity of roles and how they contribute
Expand Down
Binary file not shown.
63 changes: 56 additions & 7 deletions backend/app/services/nlg/tests/test_nlg_engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,23 +173,72 @@ async def test_generate_sentiment_text_llm_error():
assert "Failed to generate social sentiment summary due to an internal error." in parsed_response["text"]
assert respx_mock.calls.call_count == 1

assert parsed_response["section_id"] == "social_sentiment"
assert "Failed to generate social sentiment summary due to an internal error." in parsed_response["text"]
assert respx_mock.calls.call_count == 1

@pytest.mark.asyncio
async def test_generate_sentiment_text_llm_empty_content():
async def test_generate_code_audit_text_success():
engine = ConcreteNLGEngine()
raw_data = {
"overall_sentiment_score": 0.75,
"community_perception": "positive"
code_data = {"files": [{"name": "main.py", "lines": 100}]}
audit_data = {"risks": [{"type": "security", "severity": "high"}]}
expected_llm_response = {
"choices": [{"message": {"content": "Code audit summary: Clarity is good. High security risk identified. Recent code activity. Good repository quality."}}]
}

with respx.mock as respx_mock:
respx_mock.post("https://api.openai.com/v1/chat/completions").return_value = Response(200, json=expected_llm_response)

response = await engine.generate_code_audit_text(code_data, audit_data)
parsed_response = json.loads(response)

assert parsed_response["section_id"] == "code_audit_summary"
assert "Code audit summary: Clarity is good." in parsed_response["text"]
assert respx_mock.calls.call_count == 1

@pytest.mark.asyncio
async def test_generate_code_audit_text_empty_data():
engine = ConcreteNLGEngine()
code_data = {}
audit_data = {}

response = await engine.generate_code_audit_text(code_data, audit_data)
parsed_response = json.loads(response)

assert parsed_response["section_id"] == "code_audit_summary"
assert "Code audit and repository data are not available at this time." in parsed_response["text"]

@pytest.mark.asyncio
async def test_generate_code_audit_text_llm_error():
engine = ConcreteNLGEngine()
code_data = {"files": [{"name": "main.py", "lines": 100}]}
audit_data = {"risks": [{"type": "security", "severity": "high"}]}

with respx.mock as respx_mock:
respx_mock.post("https://api.openai.com/v1/chat/completions").return_value = Response(500, text="Internal Server Error")

response = await engine.generate_code_audit_text(code_data, audit_data)
parsed_response = json.loads(response)

assert parsed_response["section_id"] == "code_audit_summary"
assert "Failed to generate code audit summary due to an internal error." in parsed_response["text"]
assert respx_mock.calls.call_count == 1

@pytest.mark.asyncio
async def test_generate_code_audit_text_llm_empty_content():
engine = ConcreteNLGEngine()
code_data = {"files": [{"name": "main.py", "lines": 100}]}
audit_data = {"risks": [{"type": "security", "severity": "high"}]}
expected_llm_response = {
"choices": [{"message": {"content": ""}}]
}

with respx.mock as respx_mock:
respx_mock.post("https://api.openai.com/v1/chat/completions").return_value = Response(200, json=expected_llm_response)

response = await engine.generate_sentiment_text(raw_data)
response = await engine.generate_code_audit_text(code_data, audit_data)
parsed_response = json.loads(response)

assert parsed_response["section_id"] == "social_sentiment"
assert "Failed to generate social sentiment summary due to an internal error." in parsed_response["text"]
assert parsed_response["section_id"] == "code_audit_summary"
assert "Failed to generate code audit summary due to an internal error." in parsed_response["text"]
assert respx_mock.calls.call_count == 1