Spaces:
Running
Running
File size: 4,402 Bytes
6a71f13 227e75d 6a71f13 227e75d 6a71f13 227e75d 6a71f13 227e75d 6a71f13 227e75d 6a71f13 227e75d 6a71f13 227e75d e32a461 6a71f13 e32a461 6a71f13 b545e4b 6a71f13 227e75d 6a71f13 227e75d 6a71f13 227e75d 6a71f13 227e75d 6a71f13 227e75d |
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 105 106 107 108 109 |
from typing import Optional, List, Dict, Any
import openai
import anthropic
from dataclasses import dataclass
from config.llm_settings import LLMSettings
from core.file_scanner import FileInfo
@dataclass
class Message:
role: str
content: str
class LLMService:
MAX_TURNS = 5
def __init__(self):
"""LLMサービスの初期化"""
self.settings = LLMSettings()
self.current_model = self.settings.default_llm
# API クライアントの初期化
if self.settings.anthropic_api_key:
self.claude_client = anthropic.Anthropic(api_key=self.settings.anthropic_api_key)
if self.settings.openai_api_key:
openai.api_key = self.settings.openai_api_key
self.conversation_history: List[Message] = []
def switch_model(self, model: str):
"""使用するモデルを切り替え"""
if model not in self.settings.get_available_models():
raise ValueError(f"モデル {model} は利用できません")
self.current_model = model
def create_prompt(self, content: str, query: str) -> str:
"""プロンプトを生成"""
return f"""以下はGitHubリポジトリのコード解析結果です。このコードについて質問に答えてください。
コード解析結果:
{content}
質問: {query}
できるだけ具体的に、コードの内容を参照しながら回答してください。"""
def _add_to_history(self, role: str, content: str):
"""会話履歴に追加(最大5ターン)"""
self.conversation_history.append(Message(role=role, content=content))
# 最大ターン数を超えた場合、古い会話を削除
if len(self.conversation_history) > self.MAX_TURNS * 2: # 各ターンは質問と回答で2メッセージ
self.conversation_history = self.conversation_history[-self.MAX_TURNS * 2:]
def _format_messages_for_claude(self) -> List[Dict[str, str]]:
"""Claude用にメッセージをフォーマット"""
return [{"role": msg.role, "content": msg.content}
for msg in self.conversation_history]
def _format_messages_for_gpt(self) -> List[Dict[str, str]]:
"""GPT用にメッセージをフォーマット"""
return [
{"role": "system", "content": "あなたはコードアナリストとして、リポジトリの解析と質問への回答を行います。"},
*[{"role": msg.role, "content": msg.content}
for msg in self.conversation_history]
]
def get_conversation_history(self) -> List[Dict[str, str]]:
"""会話履歴を取得"""
return [{"role": msg.role, "content": msg.content}
for msg in self.conversation_history]
def clear_history(self):
"""会話履歴をクリア"""
self.conversation_history = []
def get_response(self, content: str, query: str) -> tuple[Optional[str], Optional[str]]:
"""LLMを使用して回答を生成"""
try:
prompt = self.create_prompt(content, query)
self._add_to_history("user", prompt)
if self.current_model == 'Claude':
response = self.claude_client.messages.create(
model="claude-3-5-sonnet-latest",
messages=self._format_messages_for_claude()
)
answer = response.content[0].text
else: # gpt
response = openai.ChatCompletion.create(
model="gpt-4o",
messages=self._format_messages_for_gpt()
)
answer = response.choices[0].message.content
self._add_to_history("assistant", answer)
return answer, None
except Exception as e:
return None, f"エラーが発生しました: {str(e)}"
@staticmethod
def format_code_content(files: List[FileInfo]) -> str:
"""ファイル内容をプロンプト用にフォーマット"""
formatted_content = []
for file_info in files:
formatted_content.append(
f"#ファイルパス\n{file_info.path}\n------------\n{file_info.content}\n"
)
return "\n".join(formatted_content) |