copilot-api
bash
https://github.com/ericc-ch/copilot-api
bash
# 一键构建并运行
docker build -t bun-app . && docker run -d -p 4141:4141 --name bun-app bun-app
# 查看实时日志
docker logs -f bun-app
# 停止并删除
docker rm -f bun-app
需要从github上输入验证码进行验证登录。
python测试脚本:
python
#!/usr/bin/env python3
# geogebra_copilot_test.py
import requests
import json
import time
from typing import List, Dict, Optional
class GeoGebraCopilotTester:
def __init__(self, base_url: str = "http://localhost:4141"):
self.base_url = base_url
self.session = requests.Session()
self.session.headers.update({"Content-Type": "application/json"})
self.conversation_history = []
def generate_code(self, prompt: str, system_prompt: str = None) -> Optional[str]:
"""生成 GeoGebra 代码"""
messages = []
if system_prompt:
messages.append({"role": "system", "content": system_prompt})
messages.append({"role": "user", "content": prompt})
payload = {"model": "gpt-4", # 使用测试中成功的模型
"messages": messages, "temperature": 0.3, "max_tokens": 1000}
try:
response = self.session.post(f"{self.base_url}/v1/chat/completions", json=payload)
if response.status_code == 200:
data = response.json()
code = data['choices'][0]['message']['content']
return code
else:
print(f"错误: {response.status_code} - {response.text}")
return None
except Exception as e:
print(f"异常: {e}")
return None
def chat_with_context(self, user_message: str) -> Optional[str]:
"""带上下文的对话(保持会话历史)"""
self.conversation_history.append({"role": "user", "content": user_message})
payload = {"model": "gpt-4", "messages": self.conversation_history, "temperature": 0.3, "max_tokens": 1000}
try:
response = self.session.post(f"{self.base_url}/v1/chat/completions", json=payload)
if response.status_code == 200:
data = response.json()
assistant_message = data['choices'][0]['message']['content']
self.conversation_history.append({"role": "assistant", "content": assistant_message})
return assistant_message
else:
print(f"错误: {response.status_code}")
return None
except Exception as e:
print(f"异常: {e}")
return None
def clear_context(self):
"""清除对话历史"""
self.conversation_history = []
print("对话历史已清除")
def test_basic_shapes(self):
"""测试基本几何图形生成"""
print("\n" + "=" * 60)
print("测试 1: 基本几何图形")
print("=" * 60)
tests = [("三角形", "画一个等边三角形,边长为5"), ("正方形", "画一个正方形,左下角在(0,0),边长为4"), ("圆", "画一个圆,圆心在(0,0),半径为3"), ("矩形", "画一个矩形,宽为6,高为4,左下角在(1,1)"), ]
system_prompt = "You are a GeoGebra expert. Generate only GeoGebra executable code, no explanations."
for name, prompt in tests:
print(f"\n📐 生成{name}: {prompt}")
print("-" * 40)
code = self.generate_code(prompt, system_prompt)
if code:
print(f"✅ 生成的代码:\n{code}")
else:
print(f"❌ 生成失败")
time.sleep(0.5) # 避免请求过快
def test_complex_shapes(self):
"""测试复杂图形生成"""
print("\n" + "=" * 60)
print("测试 2: 复杂图形")
print("=" * 60)
tests = [("五边形", "画一个正五边形,外接圆半径为4"), ("椭圆", "画一个椭圆,长轴为6,短轴为4,中心在(0,0)"), ("扇形", "画一个90度的扇形,圆心在(0,0),半径为5"),
("圆弧", "画一个半圆,从(0,0)到(4,0)"), ]
system_prompt = "Generate GeoGebra code. Only output the code, no explanations."
for name, prompt in tests:
print(f"\n📐 生成{name}: {prompt}")
print("-" * 40)
code = self.generate_code(prompt, system_prompt)
if code:
print(f"✅ 生成的代码:\n{code}")
else:
print(f"❌ 生成失败")
time.sleep(0.5)
def test_multi_turn_conversation(self):
"""测试多轮对话"""
print("\n" + "=" * 60)
print("测试 3: 多轮对话")
print("=" * 60)
self.clear_context()
# 添加系统提示
self.conversation_history.append({"role": "system", "content": "You are a GeoGebra assistant. Generate only GeoGebra code, no explanations."})
# 第一轮:画三角形
print("\n👤 用户: 画一个三角形,顶点为(0,0), (3,0), (1.5, 2.6)")
response1 = self.chat_with_context("画一个三角形,顶点为(0,0), (3,0), (1.5, 2.6)")
if response1:
print(f"🤖 助手:\n{response1}")
# 第二轮:修改颜色
print("\n👤 用户: 把这个三角形涂成红色")
response2 = self.chat_with_context("把这个三角形涂成红色")
if response2:
print(f"🤖 助手:\n{response2}")
# 第三轮:添加内切圆
print("\n👤 用户: 在三角形内部画一个内切圆")
response3 = self.chat_with_context("在三角形内部画一个内切圆")
if response3:
print(f"🤖 助手:\n{response3}")
def test_geoegbra_commands(self):
"""测试特定 GeoGebra 命令"""
print("\n" + "=" * 60)
print("测试 4: GeoGebra 命令测试")
print("=" * 60)
commands = ["中点", "角平分线", "垂线", "平行线", "切线"]
system_prompt = "Generate GeoGebra code. Output only the code."
for cmd in commands:
print(f"\n📐 测试命令: {cmd}")
print("-" * 40)
prompt = f"演示如何使用GeoGebra的{cmd}命令"
code = self.generate_code(prompt, system_prompt)
if code:
print(f"✅ 生成的代码:\n{code}")
else:
print(f"❌ 生成失败")
time.sleep(0.5)
def test_error_handling(self):
"""测试错误处理"""
print("\n" + "=" * 60)
print("测试 5: 错误处理测试")
print("=" * 60)
# 测试空提示
print("\n📐 测试空提示:")
code = self.generate_code("")
if code:
print(f"✅ 响应: {code[:100]}...")
else:
print("✅ 正确处理空提示")
# 测试无效请求
print("\n📐 测试无效模型:")
try:
payload = {"model": "invalid_model_name", "messages": [{"role": "user", "content": "test"}]}
response = self.session.post(f"{self.base_url}/v1/chat/completions", json=payload)
print(f"状态码: {response.status_code}")
if response.status_code == 400:
print("✅ 正确处理无效模型")
except Exception as e:
print(f"错误处理: {e}")
def get_usage_info(self):
"""获取使用统计"""
print("\n" + "=" * 60)
print("使用统计")
print("=" * 60)
try:
# 获取使用情况
response = self.session.get(f"{self.base_url}/usage")
if response.status_code == 200:
data = response.json()
print("✅ 使用情况:")
print(json.dumps(data, indent=2, ensure_ascii=False)[:500])
else:
print("⚠️ 无法获取使用情况")
except Exception as e:
print(f"获取使用情况失败: {e}")
try:
# 获取模型列表
response = self.session.get(f"{self.base_url}/v1/models")
if response.status_code == 200:
data = response.json()
models = data.get('data', [])
print(f"\n✅ 可用模型 ({len(models)}个):")
for model in models[:10]: # 只显示前10个
print(f" - {model.get('id')}")
except Exception as e:
print(f"获取模型列表失败: {e}")
def run_all_tests(self):
"""运行所有测试"""
print("=" * 60)
print("GeoGebra Copilot API 完整测试")
print("=" * 60)
# 获取使用信息
self.get_usage_info()
# 运行测试
self.test_basic_shapes()
self.test_complex_shapes()
self.test_multi_turn_conversation()
self.test_geoegbra_commands()
self.test_error_handling()
print("\n" + "=" * 60)
print("所有测试完成!")
print("=" * 60)
def main():
tester = GeoGebraCopilotTester("http://localhost:4141")
tester.run_all_tests()
if __name__ == "__main__":
main()