fix: use /api/chat endpoint for proper multi-turn conversations (issue #10)
- Replace /api/generate with /api/chat endpoint - Send messages as proper list with role/content structure - Preserve multi-turn semantics (system/user/assistant roles) - Compatible with OpenAI-compatible endpoints - Filter invalid message roles before sending
This commit is contained in:
parent
b25fb3c1c6
commit
3bb50c4925
@ -106,15 +106,18 @@ class APIClient:
|
|||||||
self, messages: list, model: str = None, **kwargs
|
self, messages: list, model: str = None, **kwargs
|
||||||
) -> Dict[str, Any]:
|
) -> Dict[str, Any]:
|
||||||
"""
|
"""
|
||||||
Get a completion from the LLM using Ollama chat endpoint
|
Get a completion from the LLM using Ollama chat endpoint.
|
||||||
|
|
||||||
|
Uses /api/chat with proper message list format to preserve
|
||||||
|
multi-turn conversation semantics (system, user, assistant roles).
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
messages (list): List of message dictionaries (roles and content)
|
messages (list): List of message dictionaries with 'role' and 'content'
|
||||||
model (str): Model to use
|
model (str): Model to use
|
||||||
**kwargs: Additional parameters for the API
|
**kwargs: Additional parameters for the API
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
dict: Response from the LLM
|
dict: Response from the LLM in OpenAI-compatible format
|
||||||
"""
|
"""
|
||||||
if model is None:
|
if model is None:
|
||||||
# Reload config to get latest model setting
|
# Reload config to get latest model setting
|
||||||
@ -123,40 +126,53 @@ class APIClient:
|
|||||||
current_config = load_config()
|
current_config = load_config()
|
||||||
model = current_config.get("model", "qwen3-coder:30b")
|
model = current_config.get("model", "qwen3-coder:30b")
|
||||||
|
|
||||||
# Convert messages to prompt format expected by Ollama generate endpoint
|
# Filter messages to only include valid roles for chat endpoint
|
||||||
prompt_text = ""
|
chat_messages = []
|
||||||
for message in messages:
|
for message in messages:
|
||||||
role = message.get("role", "user")
|
role = message.get("role", "user")
|
||||||
content = message.get("content", "")
|
content = message.get("content", "")
|
||||||
|
if role in ("system", "user", "assistant"):
|
||||||
|
chat_messages.append({"role": role, "content": content})
|
||||||
|
|
||||||
# Format messages properly for the model
|
if not chat_messages:
|
||||||
if role == "system":
|
return {"error": "No valid messages provided for chat completion"}
|
||||||
prompt_text += f"System: {content}\n\n"
|
|
||||||
elif role == "assistant":
|
|
||||||
prompt_text += f"Assistant: {content}\n\n"
|
|
||||||
else: # user
|
|
||||||
prompt_text += f"User: {content}\n\n"
|
|
||||||
|
|
||||||
# Add instruction for assistant response
|
# Use Ollama chat endpoint with proper message format
|
||||||
prompt_text += "Assistant:"
|
data = {
|
||||||
|
"model": model,
|
||||||
|
"messages": chat_messages,
|
||||||
|
"stream": False,
|
||||||
|
**kwargs,
|
||||||
|
}
|
||||||
|
|
||||||
# Prepare the data for Ollama generate endpoint
|
result = self._make_request("/api/chat", "POST", data)
|
||||||
data = {"model": model, "prompt": prompt_text, "stream": False, **kwargs}
|
|
||||||
|
|
||||||
result = self._make_request("/api/generate", "POST", data)
|
|
||||||
if not result["success"]:
|
if not result["success"]:
|
||||||
return {"error": result["error"]}
|
return {"error": result["error"]}
|
||||||
|
|
||||||
# Extract the response from Ollama's generate format
|
# Extract the response from Ollama's chat format
|
||||||
try:
|
try:
|
||||||
response_data = result["data"]
|
response_data = result["data"]
|
||||||
# In Ollama generate responses, the actual text is in the "response" field
|
# Ollama chat endpoint returns message in message.content
|
||||||
if "response" in response_data:
|
if "message" in response_data:
|
||||||
|
return {
|
||||||
|
"choices": [
|
||||||
|
{
|
||||||
|
"message": {
|
||||||
|
"role": response_data["message"].get(
|
||||||
|
"role", "assistant"
|
||||||
|
),
|
||||||
|
"content": response_data["message"].get(
|
||||||
|
"content", ""
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
elif "response" in response_data:
|
||||||
return {
|
return {
|
||||||
"choices": [{"message": {"content": response_data["response"]}}]
|
"choices": [{"message": {"content": response_data["response"]}}]
|
||||||
}
|
}
|
||||||
else:
|
else:
|
||||||
# If we get a different format, return what we found
|
|
||||||
return response_data
|
return response_data
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return {"error": f"Failed to process chat completion result: {str(e)}"}
|
return {"error": f"Failed to process chat completion result: {str(e)}"}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user