|
16 | 16 | from instrumentation import setup_tracing |
17 | 17 | setup_tracing(project_name="cortex") |
18 | 18 |
|
19 | | -from anthropic import Anthropic |
| 19 | +import litellm |
20 | 20 | from redis_store import search_context, get_recent_context |
21 | 21 |
|
22 | | -client = Anthropic(api_key=os.environ.get("ANTHROPIC_API_KEY")) |
| 22 | +# Model routed through LiteLLM: keep Claude as the default, but any provider |
| 23 | +# LiteLLM supports works by setting CORTEX_MODEL (e.g. "openai/gpt-4o", |
| 24 | +# "gemini/gemini-2.5-pro", "bedrock/..."). Credentials come from that |
| 25 | +# provider's own env var (ANTHROPIC_API_KEY by default). |
| 26 | +DEFAULT_MODEL = os.environ.get("CORTEX_MODEL", "claude-opus-4-5") |
23 | 27 |
|
24 | 28 | # ── Page config ─────────────────────────────────────────────────────────────── |
25 | 29 |
|
@@ -119,24 +123,29 @@ def ask_cortex(question: str, context_chunks: list[dict]) -> str: |
119 | 123 | for c in context_chunks |
120 | 124 | ]) |
121 | 125 |
|
122 | | - response = client.messages.create( |
123 | | - model="claude-opus-4-5", |
124 | | - max_tokens=1000, |
125 | | - system="""You are Cortex — a personal AI that knows everything about the user based on their captured context. |
| 126 | + system_prompt = """You are Cortex — a personal AI that knows everything about the user based on their captured context. |
126 | 127 |
|
127 | 128 | You have access to the user's second brain: notes, decisions, insights, and memories captured from their AI chats, Slack, iMessage, and other apps. |
128 | 129 |
|
129 | 130 | Answer questions directly and personally, as if you are their most knowledgeable assistant. |
130 | 131 | - Reference specific details from the context (dates, sources, exact decisions) |
131 | 132 | - Be concise but complete |
132 | 133 | - If the context is partial, say so and answer with what you have |
133 | | -- Never say "based on the provided context" — just answer naturally""", |
134 | | - messages=[{ |
135 | | - "role": "user", |
136 | | - "content": f"Context from my second brain:\n\n{context_text}\n\n---\n\nQuestion: {question}" |
137 | | - }] |
| 134 | +- Never say "based on the provided context" — just answer naturally""" |
| 135 | + response = litellm.completion( |
| 136 | + model=DEFAULT_MODEL, |
| 137 | + max_tokens=1000, |
| 138 | + messages=[ |
| 139 | + {"role": "system", "content": system_prompt}, |
| 140 | + { |
| 141 | + "role": "user", |
| 142 | + "content": f"Context from my second brain:\n\n{context_text}\n\n---\n\nQuestion: {question}", |
| 143 | + }, |
| 144 | + ], |
| 145 | + # Drop provider-unsupported params so one config works across providers. |
| 146 | + drop_params=True, |
138 | 147 | ) |
139 | | - return response.content[0].text |
| 148 | + return response.choices[0].message.content or "" |
140 | 149 |
|
141 | 150 |
|
142 | 151 | # ── Sidebar ─────────────────────────────────────────────────────────────────── |
|
0 commit comments