Skip to content
This repository was archived by the owner on Jun 5, 2025. It is now read-only.

Commit 7212f18

Browse files
committed
fix integration tests
1 parent cb577d2 commit 7212f18

File tree

10 files changed

+65
-30
lines changed

10 files changed

+65
-30
lines changed

src/codegate/muxing/anthropic_mappers.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,10 @@ def anthropic_from_legacy_openai(request: openai.LegacyCompletionRequest):
4141
content=[
4242
anthropic.TextContent(
4343
type="text",
44-
text=request.prompt,
44+
# We default to empty string when prompt is
45+
# null since `text` field is mandatory for
46+
# Anthropic.
47+
text=request.prompt if request.prompt else "",
4548
),
4649
],
4750
),

src/codegate/muxing/router.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,12 @@ async def route_to_dest_provider(
9494
match rest_of_path:
9595
case "chat/completions":
9696
parsed = openai.ChatCompletionRequest.model_validate_json(body)
97+
case "api/v1/chat/completions":
98+
parsed = openai.ChatCompletionRequest.model_validate_json(body)
9799
case "completions":
98100
parsed = openai.LegacyCompletionRequest.model_validate_json(body)
101+
case "api/v1/completions":
102+
parsed = openai.LegacyCompletionRequest.model_validate_json(body)
99103
case _:
100104
raise ValueError(f"unknown rest of path: {rest_of_path}")
101105
is_fim_request = FIMAnalyzer.is_fim_request(rest_of_path, parsed)

src/codegate/providers/copilot/streaming.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import structlog
44
from pydantic import ValidationError
55

6-
from src.codegate.types.openai import StreamingChatCompletion
6+
from codegate.types.openai import StreamingChatCompletion
77

88
logger = structlog.get_logger("codegate")
99

src/codegate/providers/llamacpp/provider.py

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from pathlib import Path
2-
from typing import List
2+
from typing import Callable, List
33

44
import structlog
55
from fastapi import HTTPException, Request
@@ -63,10 +63,17 @@ async def process_request(
6363
base_url: str,
6464
is_fim_request: bool,
6565
client_type: ClientType,
66+
completion_handler: Callable | None = None,
67+
stream_generator: Callable | None = None,
6668
):
6769
try:
6870
stream = await self.complete(
69-
data, None, base_url, is_fim_request=is_fim_request, client_type=client_type
71+
data,
72+
None,
73+
base_url,
74+
is_fim_request=is_fim_request,
75+
client_type=client_type,
76+
completion_handler=completion_handler,
7077
)
7178
except RuntimeError as e:
7279
# propagate as error 500
@@ -82,7 +89,11 @@ async def process_request(
8289
else:
8390
# just continue raising the exception
8491
raise e
85-
return self._completion_handler.create_response(stream, client_type)
92+
return self._completion_handler.create_response(
93+
stream,
94+
client_type,
95+
stream_generator=stream_generator,
96+
)
8697

8798
def _setup_routes(self):
8899
"""

src/codegate/providers/openai/provider.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import List
1+
from typing import Callable, List
22

33
import httpx
44
import structlog
@@ -70,6 +70,8 @@ async def process_request(
7070
base_url: str,
7171
is_fim_request: bool,
7272
client_type: ClientType,
73+
completion_handler: Callable | None = None,
74+
stream_generator: Callable | None = None,
7375
):
7476
try:
7577
stream = await self.complete(
@@ -78,6 +80,7 @@ async def process_request(
7880
base_url,
7981
is_fim_request=is_fim_request,
8082
client_type=client_type,
83+
completion_handler=completion_handler,
8184
)
8285
except Exception as e:
8386
# Check if we have an status code there
@@ -88,7 +91,11 @@ async def process_request(
8891
else:
8992
# just continue raising the exception
9093
raise e
91-
return self._completion_handler.create_response(stream, client_type)
94+
return self._completion_handler.create_response(
95+
stream,
96+
client_type,
97+
stream_generator=stream_generator,
98+
)
9299

93100
def _setup_routes(self):
94101
"""

src/codegate/providers/openrouter/provider.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from typing import Callable
2+
13
from fastapi import Header, HTTPException, Request
24

35
from codegate.clients.clients import ClientType
@@ -54,8 +56,18 @@ async def process_request(
5456
base_url: str,
5557
is_fim_request: bool,
5658
client_type: ClientType,
59+
completion_handler: Callable | None = None,
60+
stream_generator: Callable | None = None,
5761
):
58-
return await super().process_request(data, api_key, base_url, is_fim_request, client_type)
62+
return await super().process_request(
63+
data,
64+
api_key,
65+
base_url,
66+
is_fim_request,
67+
client_type,
68+
completion_handler=completion_handler,
69+
stream_generator=stream_generator,
70+
)
5971

6072
def _setup_routes(self):
6173
@self.router.post(f"/{self.provider_route_name}/completions")

src/codegate/types/openai/_generators.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
import httpx
77
import structlog
88

9+
from ._legacy_models import (
10+
LegacyCompletionRequest,
11+
)
912
from ._response_models import (
1013
ChatCompletion,
1114
ErrorDetails,
@@ -53,8 +56,15 @@ async def completions_streaming(request, api_key, base_url):
5356
# TODO refactor this. This is a ugly hack, we have to fix the way
5457
# we calculate base urls.
5558
if "/v1" not in base_url:
56-
f"{base_url}/v1"
57-
async for item in streaming(request, api_key, f"{base_url}/chat/completions"):
59+
base_url = f"{base_url}/v1"
60+
61+
# TODO refactor. This is yet another Ugly hack caused by having a
62+
# single code path for both legacy and current APIs.
63+
url = f"{base_url}/chat/completions"
64+
if isinstance(request, LegacyCompletionRequest):
65+
url = f"{base_url}/completions"
66+
67+
async for item in streaming(request, api_key, url):
5868
yield item
5969

6070

src/codegate/types/openai/_response_models.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ class StreamingChatCompletion(pydantic.BaseModel):
191191
model: str | None = None # copilot extension (optional)
192192
service_tier: ServiceTier | None = None
193193
system_fingerprint: str | None = None
194-
object: Literal["chat.completion.chunk"] = "chat.completion.chunk"
194+
object: Literal["chat.completion.chunk", "text_completion"] = "chat.completion.chunk"
195195
usage: Usage | None = None
196196

197197
def get_content(self) -> Iterable[StreamingChatCompletionChoice]:

tests/integration/anthropic/testcases.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ headers:
33
x-api-key: ENV_ANTHROPIC_KEY
44

55
muxing:
6-
mux_url: http://127.0.0.1:8989/v1/mux/
7-
trimm_from_testcase_url: http://127.0.0.1:8989/anthropic/
6+
mux_url: http://127.0.0.1:8989/v1/mux/chat/completions
7+
trimm_from_testcase_url: http://127.0.0.1:8989/anthropic/messages
88
provider_endpoint:
99
url: http://127.0.0.1:8989/api/v1/provider-endpoints
1010
headers:

tests/integration/openrouter/testcases.yaml

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -60,29 +60,17 @@ testcases:
6060
url: http://localhost:8989/openrouter/completions
6161
data: |
6262
{
63-
"top_k": 50,
64-
"temperature": 0,
65-
"max_tokens": 4096,
6663
"model": "anthropic/claude-3-5-haiku-20241022",
67-
"stop_sequences": [
64+
"max_tokens": 4096,
65+
"temperature": 0,
66+
"stream": true,
67+
"stop": [
6868
"</COMPLETION>",
6969
"/src/",
7070
"#- coding: utf-8",
7171
"```"
7272
],
73-
"stream": true,
74-
"messages": [
75-
{
76-
"role": "user",
77-
"content": [
78-
{
79-
"type": "text",
80-
"text": "You are a HOLE FILLER. You are provided with a file containing holes, formatted as '{{HOLE_NAME}}'. Your TASK is to complete with a string to replace this hole with, inside a <COMPLETION/> XML tag, including context-aware indentation, if needed. All completions MUST be truthful, accurate, well-written and correct.\n\n## EXAMPLE QUERY:\n\n<QUERY>\nfunction sum_evens(lim) {\n var sum = 0;\n for (var i = 0; i < lim; ++i) {\n {{FILL_HERE}}\n }\n return sum;\n}\n</QUERY>\n\nTASK: Fill the {{FILL_HERE}} hole.\n\n## CORRECT COMPLETION\n\n<COMPLETION>if (i % 2 === 0) {\n sum += i;\n }</COMPLETION>\n\n## EXAMPLE QUERY:\n\n<QUERY>\ndef sum_list(lst):\n total = 0\n for x in lst:\n {{FILL_HERE}}\n return total\n\nprint sum_list([1, 2, 3])\n</QUERY>\n\n## CORRECT COMPLETION:\n\n<COMPLETION> total += x</COMPLETION>\n\n## EXAMPLE QUERY:\n\n<QUERY>\n// data Tree a = Node (Tree a) (Tree a) | Leaf a\n\n// sum :: Tree Int -> Int\n// sum (Node lft rgt) = sum lft + sum rgt\n// sum (Leaf val) = val\n\n// convert to TypeScript:\n{{FILL_HERE}}\n</QUERY>\n\n## CORRECT COMPLETION:\n\n<COMPLETION>type Tree<T>\n = {$:\"Node\", lft: Tree<T>, rgt: Tree<T>}\n | {$:\"Leaf\", val: T};\n\nfunction sum(tree: Tree<number>): number {\n switch (tree.$) {\n case \"Node\":\n return sum(tree.lft) + sum(tree.rgt);\n case \"Leaf\":\n return tree.val;\n }\n}</COMPLETION>\n\n## EXAMPLE QUERY:\n\nThe 5th {{FILL_HERE}} is Jupiter.\n\n## CORRECT COMPLETION:\n\n<COMPLETION>planet from the Sun</COMPLETION>\n\n## EXAMPLE QUERY:\n\nfunction hypothenuse(a, b) {\n return Math.sqrt({{FILL_HERE}}b ** 2);\n}\n\n## CORRECT COMPLETION:\n\n<COMPLETION>a ** 2 + </COMPLETION>\n\n<QUERY>\n# Path: Untitled.txt\n# http://127.0.0.1:8989/vllm/completions\n# codegate/test.py\nimport requests\n\ndef call_api():\n {{FILL_HERE}}\n\n\ndata = {'key1': 'test1', 'key2': 'test2'}\nresponse = call_api('http://localhost:8080', method='post', data='data')\n</QUERY>\nTASK: Fill the {{FILL_HERE}} hole. Answer only with the CORRECT completion, and NOTHING ELSE. Do it now.\n<COMPLETION>"
81-
}
82-
]
83-
}
84-
],
85-
"system": ""
73+
"prompt": "You are a HOLE FILLER. You are provided with a file containing holes, formatted as '{{HOLE_NAME}}'. Your TASK is to complete with a string to replace this hole with, inside a <COMPLETION/> XML tag, including context-aware indentation, if needed. All completions MUST be truthful, accurate, well-written and correct.\n\n## EXAMPLE QUERY:\n\n<QUERY>\nfunction sum_evens(lim) {\n var sum = 0;\n for (var i = 0; i < lim; ++i) {\n {{FILL_HERE}}\n }\n return sum;\n}\n</QUERY>\n\nTASK: Fill the {{FILL_HERE}} hole.\n\n## CORRECT COMPLETION\n\n<COMPLETION>if (i % 2 === 0) {\n sum += i;\n }</COMPLETION>\n\n## EXAMPLE QUERY:\n\n<QUERY>\ndef sum_list(lst):\n total = 0\n for x in lst:\n {{FILL_HERE}}\n return total\n\nprint sum_list([1, 2, 3])\n</QUERY>\n\n## CORRECT COMPLETION:\n\n<COMPLETION> total += x</COMPLETION>\n\n## EXAMPLE QUERY:\n\n<QUERY>\n// data Tree a = Node (Tree a) (Tree a) | Leaf a\n\n// sum :: Tree Int -> Int\n// sum (Node lft rgt) = sum lft + sum rgt\n// sum (Leaf val) = val\n\n// convert to TypeScript:\n{{FILL_HERE}}\n</QUERY>\n\n## CORRECT COMPLETION:\n\n<COMPLETION>type Tree<T>\n = {$:\"Node\", lft: Tree<T>, rgt: Tree<T>}\n | {$:\"Leaf\", val: T};\n\nfunction sum(tree: Tree<number>): number {\n switch (tree.$) {\n case \"Node\":\n return sum(tree.lft) + sum(tree.rgt);\n case \"Leaf\":\n return tree.val;\n }\n}</COMPLETION>\n\n## EXAMPLE QUERY:\n\nThe 5th {{FILL_HERE}} is Jupiter.\n\n## CORRECT COMPLETION:\n\n<COMPLETION>planet from the Sun</COMPLETION>\n\n## EXAMPLE QUERY:\n\nfunction hypothenuse(a, b) {\n return Math.sqrt({{FILL_HERE}}b ** 2);\n}\n\n## CORRECT COMPLETION:\n\n<COMPLETION>a ** 2 + </COMPLETION>\n\n<QUERY>\n# Path: Untitled.txt\n# http://127.0.0.1:8989/vllm/completions\n# codegate/test.py\nimport requests\n\ndef call_api():\n {{FILL_HERE}}\n\n\ndata = {'key1': 'test1', 'key2': 'test2'}\nresponse = call_api('http://localhost:8080', method='post', data='data')\n</QUERY>\nTASK: Fill the {{FILL_HERE}} hole. Answer only with the CORRECT completion, and NOTHING ELSE. Do it now.\n<COMPLETION>"
8674
}
8775
likes: |
8876
<COMPLETION>def call_api(url, method='get', data=None):

0 commit comments

Comments
 (0)