cevheri commited on
Commit
aaa82f0
·
1 Parent(s): e73254b

format: ruff format line-length 145

Browse files
app/api/chat_api.py CHANGED
@@ -8,7 +8,10 @@ from app.schema.chat_schema import (
8
  MessageResponse,
9
  PlotResponse,
10
  )
11
- from app.schema.conversation import ConversationResponse, ConversationItemResponse
 
 
 
12
  from app.service.chat_service import ChatService
13
  from app.security.auth_service import AuthService
14
  from app.core.api_response import api_response
@@ -46,7 +49,8 @@ async def create_chat_completion(
46
  @router.get("/chat/completions", response_model=List[ChatCompletionResponse])
47
  @api_response()
48
  async def list_chat_completions(
49
- request: Request, username: str = Depends(auth_service.verify_credentials)
 
50
  ):
51
  """
52
  Get all chat completions
@@ -66,7 +70,10 @@ async def list_chat_completions(
66
 
67
 
68
  # get a chat completion by id
69
- @router.get("/chat/completions/{completion_id}", response_model=ChatCompletionResponse)
 
 
 
70
  @api_response()
71
  async def retrieve_chat_completion(
72
  completion_id: str,
@@ -85,7 +92,8 @@ async def retrieve_chat_completion(
85
 
86
  # get all messages for a chat completion
87
  @router.get(
88
- "/chat/completions/{completion_id}/messages", response_model=List[MessageResponse]
 
89
  )
90
  @api_response()
91
  async def list_messages(
@@ -139,7 +147,8 @@ async def retrieve_plot(
139
  @router.get("/conversations", response_model=ConversationResponse)
140
  @api_response()
141
  async def list_conversations(
142
- request: Request, username: str = Depends(auth_service.verify_credentials)
 
143
  ):
144
  """
145
  Get all conversations
@@ -156,7 +165,10 @@ async def list_conversations(
156
  # get a conversation by id
157
 
158
 
159
- @router.get("/conversations/{completion_id}", response_model=ConversationItemResponse)
 
 
 
160
  @api_response()
161
  async def retrieve_conversation(
162
  completion_id: str,
 
8
  MessageResponse,
9
  PlotResponse,
10
  )
11
+ from app.schema.conversation import (
12
+ ConversationResponse,
13
+ ConversationItemResponse,
14
+ )
15
  from app.service.chat_service import ChatService
16
  from app.security.auth_service import AuthService
17
  from app.core.api_response import api_response
 
49
  @router.get("/chat/completions", response_model=List[ChatCompletionResponse])
50
  @api_response()
51
  async def list_chat_completions(
52
+ request: Request,
53
+ username: str = Depends(auth_service.verify_credentials),
54
  ):
55
  """
56
  Get all chat completions
 
70
 
71
 
72
  # get a chat completion by id
73
+ @router.get(
74
+ "/chat/completions/{completion_id}",
75
+ response_model=ChatCompletionResponse,
76
+ )
77
  @api_response()
78
  async def retrieve_chat_completion(
79
  completion_id: str,
 
92
 
93
  # get all messages for a chat completion
94
  @router.get(
95
+ "/chat/completions/{completion_id}/messages",
96
+ response_model=List[MessageResponse],
97
  )
98
  @api_response()
99
  async def list_messages(
 
147
  @router.get("/conversations", response_model=ConversationResponse)
148
  @api_response()
149
  async def list_conversations(
150
+ request: Request,
151
+ username: str = Depends(auth_service.verify_credentials),
152
  ):
153
  """
154
  Get all conversations
 
165
  # get a conversation by id
166
 
167
 
168
+ @router.get(
169
+ "/conversations/{completion_id}",
170
+ response_model=ConversationItemResponse,
171
+ )
172
  @api_response()
173
  async def retrieve_conversation(
174
  completion_id: str,
app/config/db.py CHANGED
@@ -3,7 +3,10 @@ from pydantic_settings import BaseSettings, SettingsConfigDict
3
 
4
  class DBConfig(BaseSettings):
5
  model_config = SettingsConfigDict(
6
- env_prefix="DB_", env_file=".env", env_file_encoding="utf-8", extra="ignore"
 
 
 
7
  )
8
 
9
  MONGO_USER: str = "root"
 
3
 
4
  class DBConfig(BaseSettings):
5
  model_config = SettingsConfigDict(
6
+ env_prefix="DB_",
7
+ env_file=".env",
8
+ env_file_encoding="utf-8",
9
+ extra="ignore",
10
  )
11
 
12
  MONGO_USER: str = "root"
app/config/log.py CHANGED
@@ -16,7 +16,10 @@ class LogConfig(BaseSettings):
16
  )
17
 
18
  model_config = SettingsConfigDict(
19
- env_prefix="LOG_", env_file=".env", env_file_encoding="utf-8", extra="ignore"
 
 
 
20
  )
21
 
22
  LEVEL: str = "DEBUG"
 
16
  )
17
 
18
  model_config = SettingsConfigDict(
19
+ env_prefix="LOG_",
20
+ env_file=".env",
21
+ env_file_encoding="utf-8",
22
+ extra="ignore",
23
  )
24
 
25
  LEVEL: str = "DEBUG"
app/config/secret.py CHANGED
@@ -5,7 +5,10 @@ class SecretConfig(BaseSettings):
5
  """Secret configuration to be set in env variables"""
6
 
7
  model_config = SettingsConfigDict(
8
- env_prefix="SECRET_", env_file=".env", env_file_encoding="utf-8", extra="ignore"
 
 
 
9
  )
10
 
11
  KEY: str = "mock-secret-key"
 
5
  """Secret configuration to be set in env variables"""
6
 
7
  model_config = SettingsConfigDict(
8
+ env_prefix="SECRET_",
9
+ env_file=".env",
10
+ env_file_encoding="utf-8",
11
+ extra="ignore",
12
  )
13
 
14
  KEY: str = "mock-secret-key"
app/core/api_response.py CHANGED
@@ -48,13 +48,9 @@ def url_to_filename(url: str, method: str) -> str:
48
  return result
49
 
50
 
51
- def get_mock_response(
52
- url_path: str, python_module_name: str, python_method_name: str
53
- ) -> Dict:
54
  """Get mock response from JSON file."""
55
- logger.trace(
56
- f"BEGIN: url_path: {url_path} python_module_name: {python_module_name} python_method_name: {python_method_name}"
57
- )
58
  filename = None
59
  file_path = None
60
  try:
@@ -115,12 +111,12 @@ def api_response():
115
  if USE_MOCK:
116
  python_method_name = func.__name__
117
  python_module_name = func.__module__
118
- logger.warning(
119
- f"Using mock response for {request.url.path} [{request.method}] > {python_module_name}.{python_method_name}"
120
- )
121
  try:
122
  result = get_mock_response(
123
- request.url.path, python_module_name, python_method_name
 
 
124
  )
125
  logger.trace(f"Mock response: {result}")
126
  return result
 
48
  return result
49
 
50
 
51
+ def get_mock_response(url_path: str, python_module_name: str, python_method_name: str) -> Dict:
 
 
52
  """Get mock response from JSON file."""
53
+ logger.trace(f"BEGIN: url_path: {url_path} python_module_name: {python_module_name} python_method_name: {python_method_name}")
 
 
54
  filename = None
55
  file_path = None
56
  try:
 
111
  if USE_MOCK:
112
  python_method_name = func.__name__
113
  python_module_name = func.__module__
114
+ logger.warning(f"Using mock response for {request.url.path} [{request.method}] > {python_module_name}.{python_method_name}")
 
 
115
  try:
116
  result = get_mock_response(
117
+ request.url.path,
118
+ python_module_name,
119
+ python_method_name,
120
  )
121
  logger.trace(f"Mock response: {result}")
122
  return result
app/model/chat_model.py CHANGED
@@ -72,11 +72,16 @@ class ChatMessage(BaseModel):
72
  role: MessageRole = Field(
73
  ...,
74
  description="The role of the message sender",
75
- examples=[MessageRole.USER, MessageRole.ASSISTANT, MessageRole.SYSTEM],
 
 
 
 
76
  )
77
  content: str = Field(..., description="The content of the message")
78
  timestamp: datetime = Field(
79
- default_factory=datetime.now, description="The timestamp of the message"
 
80
  )
81
 
82
 
@@ -97,9 +102,7 @@ class ChatCompletion(BaseModel):
97
  description="The model used for the chat completion",
98
  examples=["gpt-4o-mini", "gpt-4o", "gpt-3.5-turbo"],
99
  )
100
- messages: List[ChatMessage] = Field(
101
- ..., description="The messages in the chat completion"
102
- )
103
 
104
  # not implemented yet
105
  # temperature: float = Field(default=0.7,ge=0.0, le=1.0, description="What sampling temperature to use, between 0 and 1. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic.")
@@ -120,9 +123,7 @@ class ChatCompletion(BaseModel):
120
  default_factory=datetime.now,
121
  description="The date and time the chat completion was created",
122
  )
123
- last_updated_by: str = Field(
124
- ..., description="The user who last updated the chat completion"
125
- )
126
  last_updated_date: datetime = Field(
127
  default_factory=datetime.now,
128
  description="The date and time the chat completion was last updated",
 
72
  role: MessageRole = Field(
73
  ...,
74
  description="The role of the message sender",
75
+ examples=[
76
+ MessageRole.USER,
77
+ MessageRole.ASSISTANT,
78
+ MessageRole.SYSTEM,
79
+ ],
80
  )
81
  content: str = Field(..., description="The content of the message")
82
  timestamp: datetime = Field(
83
+ default_factory=datetime.now,
84
+ description="The timestamp of the message",
85
  )
86
 
87
 
 
102
  description="The model used for the chat completion",
103
  examples=["gpt-4o-mini", "gpt-4o", "gpt-3.5-turbo"],
104
  )
105
+ messages: List[ChatMessage] = Field(..., description="The messages in the chat completion")
 
 
106
 
107
  # not implemented yet
108
  # temperature: float = Field(default=0.7,ge=0.0, le=1.0, description="What sampling temperature to use, between 0 and 1. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic.")
 
123
  default_factory=datetime.now,
124
  description="The date and time the chat completion was created",
125
  )
126
+ last_updated_by: str = Field(..., description="The user who last updated the chat completion")
 
 
127
  last_updated_date: datetime = Field(
128
  default_factory=datetime.now,
129
  description="The date and time the chat completion was last updated",
app/repository/chat_repository.py CHANGED
@@ -17,9 +17,7 @@ class ChatRepository:
17
 
18
  result = self.db.chat_completion.update_one(query, update, upsert=True)
19
 
20
- completion_id = (
21
- str(result.upserted_id) if result.upserted_id else entity.completion_id
22
- )
23
  entity.completion_id = completion_id
24
 
25
  # save conversation if new chat completion
@@ -43,12 +41,7 @@ class ChatRepository:
43
  skip = (page - 1) * limit
44
  sort = sort if sort else {"created_date": -1}
45
 
46
- result = (
47
- self.db.chat_completion.find(query, project)
48
- .skip(skip)
49
- .limit(limit)
50
- .sort(sort)
51
- )
52
  return [ChatCompletion(**item) for item in result]
53
 
54
  def find_by_id(self, completion_id: str, project: dict = None) -> ChatCompletion:
@@ -56,9 +49,7 @@ class ChatRepository:
56
  Find a chat completion by a given id.
57
  Example : completion_id = "123"
58
  """
59
- result = self.db.chat_completion.find_one(
60
- {"completion_id": completion_id}, project
61
- )
62
  return ChatCompletion(**result)
63
 
64
  def find_messages(self, completion_id: str) -> List[ChatMessage]:
 
17
 
18
  result = self.db.chat_completion.update_one(query, update, upsert=True)
19
 
20
+ completion_id = str(result.upserted_id) if result.upserted_id else entity.completion_id
 
 
21
  entity.completion_id = completion_id
22
 
23
  # save conversation if new chat completion
 
41
  skip = (page - 1) * limit
42
  sort = sort if sort else {"created_date": -1}
43
 
44
+ result = self.db.chat_completion.find(query, project).skip(skip).limit(limit).sort(sort)
 
 
 
 
 
45
  return [ChatCompletion(**item) for item in result]
46
 
47
  def find_by_id(self, completion_id: str, project: dict = None) -> ChatCompletion:
 
49
  Find a chat completion by a given id.
50
  Example : completion_id = "123"
51
  """
52
+ result = self.db.chat_completion.find_one({"completion_id": completion_id}, project)
 
 
53
  return ChatCompletion(**result)
54
 
55
  def find_messages(self, completion_id: str) -> List[ChatMessage]:
app/schema/chat_schema.py CHANGED
@@ -41,9 +41,7 @@ class ChatCompletionRequest(ChatCompletionBase):
41
  """
42
 
43
  model: str = Field(..., description="The model to use for the chat completion")
44
- messages: List[MessageRequest] = Field(
45
- ..., description="The messages to use for the chat completion"
46
- )
47
  stream: bool = Field(..., description="Whether to stream the chat completion")
48
 
49
 
@@ -63,12 +61,8 @@ class ChoiceResponse(BaseModel):
63
  ...,
64
  description="The reason the model stopped generating tokens. This will be `stop` if the model hit a natural stop point or a provided stop sequence, `length` if the maximum number of tokens specified in the request was reached, `content_filter` if content was omitted due to a flag from our content filters",
65
  )
66
- index: int = Field(
67
- ..., description="The index of the choice in the list of choices."
68
- )
69
- message: MessageResponse = Field(
70
- ..., description="The message to use for the chat completion"
71
- )
72
  # logprobs: str = None # not implemented yet
73
 
74
 
@@ -77,12 +71,8 @@ class ChatCompletionResponse(ChatCompletionBase):
77
  Represents a chat completion response returned by model, based on the provided input.
78
  """
79
 
80
- completion_id: str = Field(
81
- ..., description="The unique identifier for the chat completion"
82
- )
83
- choices: List[ChoiceResponse] = Field(
84
- ..., description="A list of chat completion choices."
85
- )
86
  created: int = Field(
87
  ...,
88
  description="The Unix timestamp (in seconds) of when the chat completion was created.",
@@ -107,7 +97,8 @@ class PlotRequest(BaseModel):
107
  """
108
 
109
  message_id: str = Field(
110
- ..., description="The unique identifier for the message that the plot is for"
 
111
  )
112
 
113
 
@@ -122,6 +113,7 @@ class PlotResponse(BaseModel):
122
  description="The unique identifier for the chat completion that the plot is for",
123
  )
124
  message_id: str = Field(
125
- ..., description="The unique identifier for the message that the plot is for"
 
126
  )
127
  figure: dict = Field(..., description="The figure data to be visualized")
 
41
  """
42
 
43
  model: str = Field(..., description="The model to use for the chat completion")
44
+ messages: List[MessageRequest] = Field(..., description="The messages to use for the chat completion")
 
 
45
  stream: bool = Field(..., description="Whether to stream the chat completion")
46
 
47
 
 
61
  ...,
62
  description="The reason the model stopped generating tokens. This will be `stop` if the model hit a natural stop point or a provided stop sequence, `length` if the maximum number of tokens specified in the request was reached, `content_filter` if content was omitted due to a flag from our content filters",
63
  )
64
+ index: int = Field(..., description="The index of the choice in the list of choices.")
65
+ message: MessageResponse = Field(..., description="The message to use for the chat completion")
 
 
 
 
66
  # logprobs: str = None # not implemented yet
67
 
68
 
 
71
  Represents a chat completion response returned by model, based on the provided input.
72
  """
73
 
74
+ completion_id: str = Field(..., description="The unique identifier for the chat completion")
75
+ choices: List[ChoiceResponse] = Field(..., description="A list of chat completion choices.")
 
 
 
 
76
  created: int = Field(
77
  ...,
78
  description="The Unix timestamp (in seconds) of when the chat completion was created.",
 
97
  """
98
 
99
  message_id: str = Field(
100
+ ...,
101
+ description="The unique identifier for the message that the plot is for",
102
  )
103
 
104
 
 
113
  description="The unique identifier for the chat completion that the plot is for",
114
  )
115
  message_id: str = Field(
116
+ ...,
117
+ description="The unique identifier for the message that the plot is for",
118
  )
119
  figure: dict = Field(..., description="The figure data to be visualized")
app/schema/conversation.py CHANGED
@@ -6,18 +6,12 @@ from typing import List, Optional
6
  class ConversationItemResponse(BaseModel):
7
  """Represents an individual conversation record in the platform's chat history."""
8
 
9
- completion_id: str = Field(
10
- description="Unique identifier for the conversation in UUID format."
11
- )
12
- title: str = Field(
13
- description="Title or name of the conversation, describing its content or purpose."
14
- )
15
  create_time: datetime = Field(
16
  description="Timestamp when the conversation was created, in ISO 8601 format (e.g., '2025-05-22T10:54:37.569747Z')."
17
  )
18
- update_time: datetime = Field(
19
- description="Timestamp when the conversation was last updated, in ISO 8601 format."
20
- )
21
  mapping: Optional[dict] = Field(
22
  default=None,
23
  description="Optional dictionary containing additional conversation metadata or mappings, if applicable.",
@@ -34,9 +28,7 @@ class ConversationItemResponse(BaseModel):
34
  default=None,
35
  description="Identifier for the gizmo or tool associated with the conversation, if applicable.",
36
  )
37
- is_archived: bool = Field(
38
- description="Indicates whether the conversation is archived."
39
- )
40
  is_starred: Optional[bool] = Field(
41
  default=None,
42
  description="Indicates whether the conversation is marked as starred or favorite, if set.",
@@ -45,9 +37,7 @@ class ConversationItemResponse(BaseModel):
45
  default=None,
46
  description="Indicates whether the conversation is excluded from memory or history, if set.",
47
  )
48
- memory_scope: str = Field(
49
- description="Scope of the conversation's memory, e.g., 'global_enabled' for global memory access."
50
- )
51
  workspace_id: Optional[str] = Field(
52
  default=None,
53
  description="Identifier for the workspace the conversation belongs to, if applicable.",
@@ -56,14 +46,11 @@ class ConversationItemResponse(BaseModel):
56
  default=None,
57
  description="Status of any asynchronous operations related to the conversation, if applicable.",
58
  )
59
- safe_urls: List[str] = Field(
60
- description="List of URLs deemed safe for the conversation context."
61
- )
62
- blocked_urls: List[str] = Field(
63
- description="List of URLs blocked for the conversation context."
64
- )
65
  conversation_origin: Optional[str] = Field(
66
- default=None, description="Origin or source of the conversation, if specified."
 
67
  )
68
  snippet: Optional[str] = Field(
69
  default=None,
@@ -74,15 +61,7 @@ class ConversationItemResponse(BaseModel):
74
  class ConversationResponse(BaseModel):
75
  """Represents the response object containing a list of conversation records and pagination metadata from the platform."""
76
 
77
- items: List[ConversationItemResponse] = Field(
78
- description="List of conversation items representing the user's chat history."
79
- )
80
- total: int = Field(
81
- description="Total number of conversations available in the user's history."
82
- )
83
- limit: int = Field(
84
- description="Maximum number of conversation items returned in this response."
85
- )
86
- offset: int = Field(
87
- description="Starting index of the conversation items in this response, used for pagination."
88
- )
 
6
  class ConversationItemResponse(BaseModel):
7
  """Represents an individual conversation record in the platform's chat history."""
8
 
9
+ completion_id: str = Field(description="Unique identifier for the conversation in UUID format.")
10
+ title: str = Field(description="Title or name of the conversation, describing its content or purpose.")
 
 
 
 
11
  create_time: datetime = Field(
12
  description="Timestamp when the conversation was created, in ISO 8601 format (e.g., '2025-05-22T10:54:37.569747Z')."
13
  )
14
+ update_time: datetime = Field(description="Timestamp when the conversation was last updated, in ISO 8601 format.")
 
 
15
  mapping: Optional[dict] = Field(
16
  default=None,
17
  description="Optional dictionary containing additional conversation metadata or mappings, if applicable.",
 
28
  default=None,
29
  description="Identifier for the gizmo or tool associated with the conversation, if applicable.",
30
  )
31
+ is_archived: bool = Field(description="Indicates whether the conversation is archived.")
 
 
32
  is_starred: Optional[bool] = Field(
33
  default=None,
34
  description="Indicates whether the conversation is marked as starred or favorite, if set.",
 
37
  default=None,
38
  description="Indicates whether the conversation is excluded from memory or history, if set.",
39
  )
40
+ memory_scope: str = Field(description="Scope of the conversation's memory, e.g., 'global_enabled' for global memory access.")
 
 
41
  workspace_id: Optional[str] = Field(
42
  default=None,
43
  description="Identifier for the workspace the conversation belongs to, if applicable.",
 
46
  default=None,
47
  description="Status of any asynchronous operations related to the conversation, if applicable.",
48
  )
49
+ safe_urls: List[str] = Field(description="List of URLs deemed safe for the conversation context.")
50
+ blocked_urls: List[str] = Field(description="List of URLs blocked for the conversation context.")
 
 
 
 
51
  conversation_origin: Optional[str] = Field(
52
+ default=None,
53
+ description="Origin or source of the conversation, if specified.",
54
  )
55
  snippet: Optional[str] = Field(
56
  default=None,
 
61
  class ConversationResponse(BaseModel):
62
  """Represents the response object containing a list of conversation records and pagination metadata from the platform."""
63
 
64
+ items: List[ConversationItemResponse] = Field(description="List of conversation items representing the user's chat history.")
65
+ total: int = Field(description="Total number of conversations available in the user's history.")
66
+ limit: int = Field(description="Maximum number of conversation items returned in this response.")
67
+ offset: int = Field(description="Starting index of the conversation items in this response, used for pagination.")
 
 
 
 
 
 
 
 
app/security/auth_service.py CHANGED
@@ -52,7 +52,10 @@ class AuthService:
52
  )
53
 
54
  # Debug için JSON verilerini logla
55
- json_data = {"username": data["username"], "created_at": data["created_at"]}
 
 
 
56
  json_str = json.dumps(json_data)
57
  logger.trace(f"JSON data for signature: {json_str}")
58
  logger.trace(f"Secret key: {self.secret.KEY}")
 
52
  )
53
 
54
  # Debug için JSON verilerini logla
55
+ json_data = {
56
+ "username": data["username"],
57
+ "created_at": data["created_at"],
58
+ }
59
  json_str = json.dumps(json_data)
60
  logger.trace(f"JSON data for signature: {json_str}")
61
  logger.trace(f"Secret key: {self.secret.KEY}")
app/service/chat_service.py CHANGED
@@ -17,13 +17,9 @@ class ChatService:
17
  def __init__(self):
18
  self.chat_repository = ChatRepository()
19
 
20
- async def handle_chat_completion(
21
- self, request: ChatCompletionRequest
22
- ) -> ChatCompletionResponse:
23
  last_user_message = request.messages[-1].content
24
- response_content = (
25
- f"TODO implement ai-agent response for this message: {last_user_message}"
26
- )
27
  username = "admin"
28
 
29
  entity = ChatCompletion(**request.model_dump())
@@ -38,24 +34,29 @@ class ChatService:
38
  entity = self.chat_repository.save(entity)
39
 
40
  result = ChatCompletionResponse(**entity.model_dump())
41
- messages = [
42
- MessageResponse(**{"role": "assistant", "content": response_content})
43
- ] # TODO: implement ai-agent response
44
  result.choices = [
45
  ChoiceResponse(
46
- **{"index": 0, "message": messages[0], "finish_reason": "stop"}
 
 
 
 
47
  )
48
  ]
49
  return result
50
 
51
  async def find(
52
- self, query: dict, page: int, limit: int, sort: dict, project: dict = None
 
 
 
 
 
53
  ) -> List[ChatCompletion]:
54
  return self.chat_repository.find(query, page, limit, sort, project)
55
 
56
- async def find_by_id(
57
- self, completion_id: str, project: dict = None
58
- ) -> ChatCompletion:
59
  return self.chat_repository.find_by_id(completion_id, project)
60
 
61
  async def find_messages(self, completion_id: str) -> List[ChatMessage]:
 
17
  def __init__(self):
18
  self.chat_repository = ChatRepository()
19
 
20
+ async def handle_chat_completion(self, request: ChatCompletionRequest) -> ChatCompletionResponse:
 
 
21
  last_user_message = request.messages[-1].content
22
+ response_content = f"TODO implement ai-agent response for this message: {last_user_message}"
 
 
23
  username = "admin"
24
 
25
  entity = ChatCompletion(**request.model_dump())
 
34
  entity = self.chat_repository.save(entity)
35
 
36
  result = ChatCompletionResponse(**entity.model_dump())
37
+ messages = [MessageResponse(**{"role": "assistant", "content": response_content})] # TODO: implement ai-agent response
 
 
38
  result.choices = [
39
  ChoiceResponse(
40
+ **{
41
+ "index": 0,
42
+ "message": messages[0],
43
+ "finish_reason": "stop",
44
+ }
45
  )
46
  ]
47
  return result
48
 
49
  async def find(
50
+ self,
51
+ query: dict,
52
+ page: int,
53
+ limit: int,
54
+ sort: dict,
55
+ project: dict = None,
56
  ) -> List[ChatCompletion]:
57
  return self.chat_repository.find(query, page, limit, sort, project)
58
 
59
+ async def find_by_id(self, completion_id: str, project: dict = None) -> ChatCompletion:
 
 
60
  return self.chat_repository.find_by_id(completion_id, project)
61
 
62
  async def find_messages(self, completion_id: str) -> List[ChatMessage]:
gradio_chatbot.py CHANGED
@@ -15,11 +15,7 @@ env.read_env()
15
 
16
  # Hugging Face Spaces için özel yapılandırma
17
  IS_HF_SPACE = os.environ.get("SPACE_ID") is not None
18
- SPACE_URL = (
19
- "https://lokumai-openai-openapi-template.hf.space"
20
- if IS_HF_SPACE
21
- else "http://localhost:7860"
22
- )
23
 
24
  # API Configuration
25
  BASE_URL = env.str("BASE_URL", SPACE_URL)
@@ -43,6 +39,7 @@ def app_auth(username: str, password: str) -> bool:
43
  logger.debug(f"AUTH_USERNAME: {AUTH_USERNAME}")
44
  return username == AUTH_USERNAME and password == AUTH_PASSWORD
45
 
 
46
  # Custom CSS for fonts
47
  CUSTOM_CSS = """
48
  @font-face {{
@@ -183,7 +180,7 @@ class ChatAPI:
183
  logger.trace("######################## BEGIN API response #########################")
184
  logger.trace(json.dumps(result, indent=4))
185
  logger.trace("######################## END API response #########################")
186
-
187
  if "choices" in result and len(result["choices"]) > 0:
188
  message = result["choices"][0].get("message", {})
189
  figure = message.get("figure", None)
@@ -191,7 +188,9 @@ class ChatAPI:
191
  content = message.get("content", "Content not found")
192
  logger.trace(f"Last message: {content}")
193
  return MessageResponse(
194
- status=MessageStatus.SUCCESS, content=content, figure=figure
 
 
195
  )
196
  else:
197
  logger.error("Invalid API response")
@@ -200,7 +199,7 @@ class ChatAPI:
200
  content="",
201
  error="Invalid API response",
202
  )
203
-
204
  except httpx.TimeoutException:
205
  logger.error("API request timed out")
206
  return MessageResponse(
@@ -211,7 +210,9 @@ class ChatAPI:
211
  except Exception as e:
212
  logger.error(f"Error: {str(e)}")
213
  return MessageResponse(
214
- status=MessageStatus.ERROR, content="", error=f"Error: {str(e)}"
 
 
215
  )
216
 
217
 
@@ -276,13 +277,11 @@ class ChatInterface:
276
  last_message = gr.Textbox(label="Last Message", interactive=False)
277
 
278
  # Event handlers
279
- async def user_message(
280
- message: str, history: List[List[str]]
281
- ) -> Tuple[List[List[str]], str, str, str, object]:
282
  """Handle user message submission"""
283
  if not message.strip():
284
  return history, "", "Please enter a message.", "", None
285
-
286
  logger.debug(f"User message: {message}")
287
 
288
  history.append([message, ""])
@@ -301,14 +300,24 @@ class ChatInterface:
301
  except Exception as e:
302
  logger.error(f"Error creating plotly figure: {e}")
303
  figure = None
304
- history[-1][1] += (
305
- "\n\n⚠️ Graph data is not valid, cannot be displayed."
306
- )
307
  history[-1][1] = content
308
- return history, "", "Message sent successfully.", content, figure
 
 
 
 
 
 
309
  else:
310
  history[-1][1] = f"❌ {response.error}"
311
- return history, "", f"Error: {response.error}", "", None
 
 
 
 
 
 
312
 
313
  def clear_history() -> Tuple[List[List[str]], str, str, str, dict]:
314
  """Clear chat history"""
 
15
 
16
  # Hugging Face Spaces için özel yapılandırma
17
  IS_HF_SPACE = os.environ.get("SPACE_ID") is not None
18
+ SPACE_URL = "https://lokumai-openai-openapi-template.hf.space" if IS_HF_SPACE else "http://localhost:7860"
 
 
 
 
19
 
20
  # API Configuration
21
  BASE_URL = env.str("BASE_URL", SPACE_URL)
 
39
  logger.debug(f"AUTH_USERNAME: {AUTH_USERNAME}")
40
  return username == AUTH_USERNAME and password == AUTH_PASSWORD
41
 
42
+
43
  # Custom CSS for fonts
44
  CUSTOM_CSS = """
45
  @font-face {{
 
180
  logger.trace("######################## BEGIN API response #########################")
181
  logger.trace(json.dumps(result, indent=4))
182
  logger.trace("######################## END API response #########################")
183
+
184
  if "choices" in result and len(result["choices"]) > 0:
185
  message = result["choices"][0].get("message", {})
186
  figure = message.get("figure", None)
 
188
  content = message.get("content", "Content not found")
189
  logger.trace(f"Last message: {content}")
190
  return MessageResponse(
191
+ status=MessageStatus.SUCCESS,
192
+ content=content,
193
+ figure=figure,
194
  )
195
  else:
196
  logger.error("Invalid API response")
 
199
  content="",
200
  error="Invalid API response",
201
  )
202
+
203
  except httpx.TimeoutException:
204
  logger.error("API request timed out")
205
  return MessageResponse(
 
210
  except Exception as e:
211
  logger.error(f"Error: {str(e)}")
212
  return MessageResponse(
213
+ status=MessageStatus.ERROR,
214
+ content="",
215
+ error=f"Error: {str(e)}",
216
  )
217
 
218
 
 
277
  last_message = gr.Textbox(label="Last Message", interactive=False)
278
 
279
  # Event handlers
280
+ async def user_message(message: str, history: List[List[str]]) -> Tuple[List[List[str]], str, str, str, object]:
 
 
281
  """Handle user message submission"""
282
  if not message.strip():
283
  return history, "", "Please enter a message.", "", None
284
+
285
  logger.debug(f"User message: {message}")
286
 
287
  history.append([message, ""])
 
300
  except Exception as e:
301
  logger.error(f"Error creating plotly figure: {e}")
302
  figure = None
303
+ history[-1][1] += "\n\n⚠️ Graph data is not valid, cannot be displayed."
 
 
304
  history[-1][1] = content
305
+ return (
306
+ history,
307
+ "",
308
+ "Message sent successfully.",
309
+ content,
310
+ figure,
311
+ )
312
  else:
313
  history[-1][1] = f"❌ {response.error}"
314
+ return (
315
+ history,
316
+ "",
317
+ f"Error: {response.error}",
318
+ "",
319
+ None,
320
+ )
321
 
322
  def clear_history() -> Tuple[List[List[str]], str, str, str, dict]:
323
  """Clear chat history"""
main.py CHANGED
@@ -21,11 +21,7 @@ STORAGE_TYPE = env.str("STORAGE_TYPE", "mongodb")
21
 
22
  # Hugging Face Spaces için özel yapılandırma
23
  IS_HF_SPACE = os.environ.get("SPACE_ID") is not None
24
- SPACE_URL = (
25
- "https://lokumai-openai-openapi-template.hf.space"
26
- if IS_HF_SPACE
27
- else "http://localhost:7860"
28
- )
29
 
30
 
31
  @asynccontextmanager
 
21
 
22
  # Hugging Face Spaces için özel yapılandırma
23
  IS_HF_SPACE = os.environ.get("SPACE_ID") is not None
24
+ SPACE_URL = "https://lokumai-openai-openapi-template.hf.space" if IS_HF_SPACE else "http://localhost:7860"
 
 
 
 
25
 
26
 
27
  @asynccontextmanager
pyproject.toml CHANGED
@@ -18,3 +18,7 @@ dependencies = [
18
  "requests>=2.32.3",
19
  "uvicorn>=0.34.2",
20
  ]
 
 
 
 
 
18
  "requests>=2.32.3",
19
  "uvicorn>=0.34.2",
20
  ]
21
+
22
+ # ruff line length
23
+ [tool.ruff]
24
+ line-length = 145
scripts/api_key_genenerator.py CHANGED
@@ -46,9 +46,7 @@ def generate_api_key(username: str, secret_key: str) -> str:
46
  logger.debug(f"Secret key: {secret_key}")
47
 
48
  # Add HMAC signature for additional security
49
- signature = hmac.new(
50
- secret_key.encode(), json_str.encode(), hashlib.sha256
51
- ).hexdigest()
52
 
53
  logger.debug(f"Generated signature: {signature}")
54
 
@@ -69,9 +67,7 @@ def save_api_key(username: str, api_key: str, timestamp: int):
69
  api_key (str): Generated API key
70
  timestamp (int): Creation timestamp
71
  """
72
- formatted_timestamp = datetime.fromtimestamp(timestamp).strftime(
73
- "%Y-%m-%d %H:%M:%S"
74
- )
75
  with open("api_keys.txt", "a") as f:
76
  f.write(f"Username: {username}\n")
77
  f.write(f"API Key: {api_key}\n")
@@ -100,9 +96,7 @@ def main():
100
  print('curl -X POST "http://localhost:8000/v1/chat/completions" \\')
101
  print(f' -H "Authorization: Bearer {api_key}" \\')
102
  print(' -H "Content-Type: application/json" \\')
103
- print(
104
- ' -d \'{"model": "gpt-3.5-turbo", "messages": [{"role": "user", "content": "Hello!"}]}\''
105
- )
106
 
107
  except argparse.ArgumentError:
108
  print("Please provide a username and secret key", file=sys.stderr)
 
46
  logger.debug(f"Secret key: {secret_key}")
47
 
48
  # Add HMAC signature for additional security
49
+ signature = hmac.new(secret_key.encode(), json_str.encode(), hashlib.sha256).hexdigest()
 
 
50
 
51
  logger.debug(f"Generated signature: {signature}")
52
 
 
67
  api_key (str): Generated API key
68
  timestamp (int): Creation timestamp
69
  """
70
+ formatted_timestamp = datetime.fromtimestamp(timestamp).strftime("%Y-%m-%d %H:%M:%S")
 
 
71
  with open("api_keys.txt", "a") as f:
72
  f.write(f"Username: {username}\n")
73
  f.write(f"API Key: {api_key}\n")
 
96
  print('curl -X POST "http://localhost:8000/v1/chat/completions" \\')
97
  print(f' -H "Authorization: Bearer {api_key}" \\')
98
  print(' -H "Content-Type: application/json" \\')
99
+ print(' -d \'{"model": "gpt-3.5-turbo", "messages": [{"role": "user", "content": "Hello!"}]}\'')
 
 
100
 
101
  except argparse.ArgumentError:
102
  print("Please provide a username and secret key", file=sys.stderr)