注意:CODICIL处于存档模式。使用此功能时,我没有注意到编码助手的性能有任何显著差异(而且它几乎从未被调用过)。YMMV。请随意叉。
遗嘱附录
通过MCP(模型上下文协议)对Elixir项目进行语义代码搜索和分析
Codicil是一个Elixir库,为AI编码助手提供对代码库的深入语义理解。用自然语言提问,按行为查找函数,跟踪依赖关系,理解代码关系——所有这些都是通过模型上下文协议完成的。
它有什么作用?
想象一下,问你的AI编码助理:
- “查找验证用户输入的函数”
- “显示此函数的名称”
- “此模块有哪些依赖项?”
Codicil通过以下方式实现了这一点:
- 理解你的代码 -在编译过程中分析Elixir项目,提取函数、模块及其关系
- 创建语义搜索 -使用AI来理解什么代码 *做*不只是它的名字
- 连接到AI助手 -通过MCP提供与Claude、ChatGPT和其他AI编码工具配合使用的工具
主要特点
- 语义功能搜索 -通过用简单的英语描述代码的功能来查找代码
- 相关性分析 -查看函数调用图和模块关系
- 自动索引 -挂钩编译,无需手动扫描
- 多LLM支持 -与Anthropic Claude、OpenAI、Cohere、Google Gemini和Grok合作
安装和设置
通用步骤(所有项目)
这些步骤适用于Phoenix和非Phoenix项目。
步骤1:添加依赖关系
将Codicil添加到您的 mix.exs:
def deps do
[
# ... your existing dependencies
{:codicil, "~> 0.4", only: [:dev, :test]}
]
end然后安装:
mix deps.get步骤2:初始化数据库
Codicil使用SQLite存储索引代码。初始化它:
mix codicil.setup步骤3:配置环境变量
创建或编辑您的 .env 文件(或在shell中设置):
# Required: Choose your LLM provider
export CODICIL_LLM_PROVIDER=openai # or: anthropic, cohere, google, grok
# Required: Add your API key for the chosen provider
export OPENAI_API_KEY=your_key_here
# OR
export ANTHROPIC_API_KEY=your_key_here
# OR
export COHERE_API_KEY=your_key_here
# OR
export GOOGLE_API_KEY=your_key_here
# Optional: Embeddings provider (defaults to openai)
# If you want to use Voyage AI for embeddings:
# export CODICIL_EMBEDDING_PROVIDER=voyage
# export VOYAGE_API_KEY=your_voyage_key_here加载环境变量:
source .env步骤4:启用编译器跟踪器
编辑您的 mix.exs 在开发中启用Codicil的跟踪器:
def project do
[
app: :my_app,
version: "0.1.0",
elixir: "~> 1.14",
# Enable Codicil tracer in dev/test
elixirc_options: elixirc_options(Mix.env()),
deps: deps()
]
end
defp elixirc_options(:prod), do: []
defp elixirc_options(_env), do: [tracers: [Codicil.Tracer]]这确保了跟踪器只在开发和测试中运行,而不是在生产中运行。
______________________________________________________________________
凤凰城项目设置
如果您使用的是Phoenix,请继续执行这些步骤。
步骤5(Phoenix):将MCP路由添加到路由器
将Codicil MCP端点添加到您的Phoenix路由器。编辑 lib/my_app_web/router.ex:
defmodule MyAppWeb.Endpoint do
# ... your endpoint stuff
# Codicil MCP endpoint (only available when Codicil is loaded)
if Code.ensure_loaded?(Codicil) do
plug Codicil.Plug
end
end步骤6(Phoenix):启动Phoenix并编译
启动您的Phoenix服务器:
mix phx.serverMCP服务器将在 http://localhost:4000/codicil/mcp (或您配置的Phoenix端口)。
编译项目以触发索引:
# In another terminal
mix compile --force查看Phoenix日志,查看正在索引的函数!
______________________________________________________________________
非凤凰城项目设置
如果您没有使用Phoenix,请继续执行这些步骤。
第5步(非凤凰):添加土匪依赖
添加Bandit以服务于MCP端点。编辑 mix.exs:
def deps do
[
# ... your existing dependencies
{:codicil, "~> 0.4", only: [:dev, :test]},
{:bandit, "~> 1.6", only: :dev} # HTTP server for MCP
]
end安装:
mix deps.get步骤6(非Phoenix):为MCP服务器添加Mix别名
添加Mix别名以启动MCP服务器。编辑您的 mix.exs:
def project do
[
# ... other config
aliases: aliases()
]
end
defp aliases do
[
# ... your existing aliases (if any)
codicil: "run --no-halt -e 'Bandit.start_link(plug: Codicil.Plug, port: 4700)'"
]
end步骤6a(非Phoenix,可选):组合多个MCP服务器
如果你想同时运行多个MCP服务器(例如,Codicil+Tidewave),你可以将它们组合在一个Mix别名中:
defp aliases do
[
# ... your existing aliases (if any)
mcp: "run --no-halt -e 'Agent.start(fn -> Bandit.start_link(plug: Codicil.Plug, port: 4700); Bandit.start_link(plug: Tidewave, port: 4000) end)'"
]
end这将启动同一代理中的两个MCP服务器:
- 在上协调MCP服务器
http://localhost:4700/codicil/mcp - Tidewave MCP服务器上
http://localhost:4700/tidewave/mcp
备注:每个MCP服务器都需要自己的端口。根据需要调整端口号。
步骤7(非Phoenix):启动MCP服务器并编译
启动MCP服务器:
mix codicilMCP服务器将启动 http://localhost:4700/codicil/mcp.
在第二个终端中,编译您的项目以触发索引:
mix compile --force查看终端1中的日志,查看正在索引的函数!
______________________________________________________________________
配置您的AI助手
Codicil运行后,配置您的AI助手(Claude Desktop、Cline等)连接到MCP服务器:
凤凰项目:
- 统一资源定位符:
http://localhost:4000/codicil/mcp(使用您的Phoenix端口) - 运输:HTTP与SSE
非凤凰城项目:
- 统一资源定位符:
http://localhost:4700/codicil/mcp - 运输:HTTP与SSE
以下MCP工具现已可用:
find_similar_functions-按描述进行语义搜索list_function_callers-查找调用函数的内容(对调试和重构很有用)list_function_callees-查找函数调用的内容(对调试和重构很有用)list_module_dependencies-分析模块依赖关系get_function_source_code-获取带有上下文的完整函数源(使用而不是grep)
验证它是否正常工作
凤凰项目:
# Check that the MCP endpoint is responding
curl http://localhost:4000/codicil/mcp
# Check indexed functions
sqlite3 deps/codicil/priv/codicil.db "SELECT module, name, arity FROM functions LIMIT 10;"非凤凰城项目:
# Check that the MCP server is responding
curl http://localhost:4700/codicil/mcp
# Check indexed functions
sqlite3 deps/codicil/priv/codicil.db "SELECT module, name, arity FROM functions LIMIT 10;"运作原理
在编译过程中,编目:
- 通过以下方式捕获模块/功能定义
Codicil.Tracer - 从字节码中提取文档和关系
- 使用LLM(速率受限、异步)生成语义摘要
- 为语义搜索创建向量嵌入
- 将所有内容存储在本地SQLite数据库中
- 监视文件更改并自动重新编译
然后,你的AI助手通过MCP工具查询这些数据。
建筑
Compilation → Tracer → ModuleTracer GenServer → RateLimiter → LLM/Embeddings
↓
SQLite Database
(functions, modules,
call graph, vectors)
↓
MCP Tools
↓
AI Assistant技术栈:
- SQLite与
sqlite-vec矢量搜索的扩展 - Ecto用于数据库访问
- 用于自动代码分析的编译器跟踪器
- 多家法学硕士提供商(Anthropic、OpenAI、Cohere、谷歌、Grok)
- 通过Bandit+Plug连接MCP服务器
- 用于自动重新编译的文件系统监视器
MCP工具参考
查找类似函数
使用向量相似度搜索通过语义描述查找函数:
{
"description": "functions that validate email addresses",
"limit": 10
}list_function_ncallers
查找调用特定函数的内容(对于重构期间的调试和影响分析非常有用):
{
"moduleName": "MyApp.User",
"functionName": "create",
"arity": 1
}list_function_callees
查找函数调用的内容(对于调试执行路径和重构很有用):
{
"moduleName": "MyApp.Orders",
"functionName": "process",
"arity": 1
}list_module_dependency
分析模块依赖关系(导入、别名、使用、要求和运行时调用):
{
"moduleName": "MyApp.Accounts"
}get_function_source_code
获取包含模块指令和位置的完整函数源代码。 用这个代替 grep 或读取文件以获取完整上下文。
{
"moduleName": "MyApp.User",
"functionName": "create",
"arity": 1
}高级配置
自定义工具说明
您可以在编译时覆盖默认的MCP工具描述,以优化您的AI助手使用这些工具的方式。不同的模型(Claude、GPT-4、Codex等)可能对工具的描述方式有不同的偏好,因此定制描述可以提高工具选择的准确性,减少不必要的工具调用。
要查看当前的默认描述,请使用IEx:
iex -S mix
iex> Codicil.MCP.Tool.get_description(Codicil.MCP.Tools.FindSimilarFunctions)要自定义描述,请添加到 config/config.exs (或 config/dev.exs):
config :codicil, Codicil.MCP.Tools.FindSimilarFunctions, """
Find functions by semantic description. Use this when searching for functionality
by behavior rather than by name. Returns ranked results with code snippets.
"""
# Other configurable tool modules:
# - Codicil.MCP.Tools.ListFunctionCallers
# - Codicil.MCP.Tools.ListFunctionCallees
# - Codicil.MCP.Tools.ListModuleDependencies
# - Codicil.MCP.Tools.GetFunctionSourceCode更改工具描述后,重新编译:
mix clean
mix compile定制型号
替代默认模型:
export CODICIL_LLM_MODEL=claude-3-5-sonnet-20241022
export CODICIL_EMBEDDING_MODEL=voyage-3单独的嵌入提供程序
使用其他提供程序进行嵌入:
export CODICIL_LLM_PROVIDER=anthropic
export CODICIL_EMBEDDING_PROVIDER=openai
export ANTHROPIC_API_KEY=your_claude_key
export OPENAI_API_KEY=your_openai_key本地LLM支持(兼容OpenAI)
export CODICIL_LLM_PROVIDER=openai
export OPENAI_API_KEY=dummy
export OPENAI_BASE_URL=http://localhost:11434/v1 # e.g., Ollama
export CODICIL_LLM_MODEL=llama3故障排除
“函数未被索引”
解决方案:
- 验证是否设置了环境变量:
echo $CODICIL_LLM_PROVIDER - 检查MCP服务器是否正在运行:
curl http://localhost:4000/codicil/mcp(凤凰城)或curl http://localhost:4700/codicil/mcp(非凤凰城) - 强制重新编译:
mix compile --force - 检查日志中的跟踪器错误
“找不到数据库”
解决方案:
- 初始化数据库:
mix codicil.setup
“端口4700已在使用中”(非Phoenix)
解决方案:
- 检查端口的使用情况:
lsof -i :4700 - 终止进程或更改Mix别名中的端口
“未找到路线”(凤凰城)
解决方案:确保您添加了 forward "/codicil/mcp", Codicil.Plug 路由到Phoenix路由器并重新启动服务器。
跟踪器未运行
解决方案:验证是否在您的 mix.exs:
defp elixirc_options(_env), do: [tracers: [Codicil.Tracer]]强制重新编译:
mix clean
mix compile发展
为Codicil做出贡献?以下是如何设置开发环境:
# Clone the repository
git clone https://github.com/yourusername/codicil.git
cd codicil
# Install dependencies
mix deps.get
# Set up database
mix codicil.setup
# Run tests
mix test
# Format code
mix format数据库模式
Codicil使用SQLite和下表:
- 函数 -带有摘要和嵌入的函数定义
- 模块 -模块定义
- 函数调用 -调用图边
- 模块依赖关系 -导入/别名/使用/要求关系
矢量搜索由 sqlite-vec 扩展。
生产警告
不要将Codicil部署到生产环境。 Codicil是一个开发工具,它:
- 进行LLM API调用(成本)
- 运行时索引代码(性能开销)
- 运行HTTP服务器(安全表面)
始终将Codicil作为 :dev 唯一依赖:
{:codicil, "~> 0.6", only: [:dev, :test]}上面显示的跟踪器配置(elixirc_options(:prod), do: [])确保在生产版本中禁用Codicil。
文档
完整文档可在以下网址获得:
- HexDocs: https://hexdocs.pm/codicil
- MCP协议规范: https://spec.modelcontextprotocol.io
致谢
Codicil的设计灵感来源于 GraphSense,一个TypeScript/Node.js语义代码搜索工具。GraphSense率先将向量相似性搜索与LLM验证相结合,以实现准确的代码发现。
许可证
MIT许可证-有关详细信息,请参阅许可证文件。
